summaryrefslogtreecommitdiffstats
path: root/src/calendar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/calendar.cpp')
-rw-r--r--src/calendar.cpp250
1 files changed, 115 insertions, 135 deletions
diff --git a/src/calendar.cpp b/src/calendar.cpp
index 492cdbc..dcb96d7 100644
--- a/src/calendar.cpp
+++ b/src/calendar.cpp
@@ -4,136 +4,123 @@
4#include <ctime> 4#include <ctime>
5 5
6/*以下为"calendar.h规定之量*/ 6/*以下为"calendar.h规定之量*/
7double pi=3.14159265358979323846; 7double pi = 3.14159265358979323846;
8double day=86400; 8double day = 86400;
9double delta=1e-11; 9double delta = 1e-11;
10char jieqi[25][10]={"冬至","小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"}; 10char jieqi[25][10] = {"冬至", "小寒", "大寒", "立春", "雨水", "惊蛰", "春分",
11 "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑",
12 "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降",
13 "立冬", "小雪", "大雪", "冬至"};
11 14
12/*计算需要用的类的实例化*/ 15/*计算需要用的类的实例化*/
13Julian julian; 16Julian julian;
14parameter p; 17parameter p;
15List list; 18List list;
16 19
17 20Date *input(char *argv) {
18Date* input(char* argv) 21 Date *date = new Date;
19{
20 Date* date=new Date;
21 22
22 // 输入年份,自当年元旦起算 23 // 输入年份,自当年元旦起算
23 date->tm_year=atoi(argv)-1900; 24 date->tm_year = atoi(argv) - 1900;
24 date->tm_mon=0; 25 date->tm_mon = 0;
25 date->tm_mday=1; 26 date->tm_mday = 1;
26 date->tm_hour=0; 27 date->tm_hour = 0;
27 date->tm_min=0; 28 date->tm_min = 0;
28 date->tm_sec=0; 29 date->tm_sec = 0;
29 30
30 return date; 31 return date;
31} 32}
32 33
33/*计算当年二十四节气时刻,自去年冬至到本年冬至*/ 34/*计算当年二十四节气时刻,自去年冬至到本年冬至*/
34void JieQi(Date* date) 35void JieQi(Date *date) {
35{
36 //计算起始时间为去年12月19日0时,开始寻找去年冬至 36 //计算起始时间为去年12月19日0时,开始寻找去年冬至
37 time_t time=mktime(date); 37 time_t time = mktime(date);
38 time-=13*day; 38 time -= 13 * day;
39 39
40 double t,t_end,t_middle;//采用二分法计算,t与t_end为间隔24h的两个时刻 40 double t, t_end, t_middle; //采用二分法计算,t与t_end为间隔24h的两个时刻
41 double target_angle;//目标角度 41 double target_angle; //目标角度
42 Date* date_tmp; 42 Date *date_tmp;
43 43
44 //计算每个节气对应太阳地心黄经 44 //计算每个节气对应太阳地心黄经
45 for(int i=0;i<25;i++,time+=12*day) 45 for (int i = 0; i < 25; i++, time += 12 * day) {
46 { 46 target_angle = 15 * i + 270;
47 target_angle=15*i+270; 47 if (target_angle >= 360)
48 if(target_angle>=360) 48 target_angle -= 360;
49 target_angle-=360;
50 49
51 t=julian.getJulianKiloYear(time); 50 t = julian.getJulianKiloYear(time);
52 t_end=julian.getJulianKiloYear(time+day); 51 t_end = julian.getJulianKiloYear(time + day);
53 52
54 //定春分 53 //定春分
55 if(target_angle==0) 54 if (target_angle == 0) {
56 {
57 /* 春分太阳地心视黄经为0,一般二分法不便于计算 55 /* 春分太阳地心视黄经为0,一般二分法不便于计算
58 * 因而限定范围为[355,360)∪(0,5],即春分前后各5度 56 * 因而限定范围为[355,360)∪(0,5],即春分前后各5度
59 * 当t_end时刻太阳地心视黄经在[355,360)时,证明春分在后边,t和t_end前进24h 57 * 当t_end时刻太阳地心视黄经在[355,360)时,证明春分在后边,t和t_end前进24h
60 */ 58 */
61 while(p.sun_longitude(t_end)<360&&p.sun_longitude(t_end)>355) 59 while (p.sun_longitude(t_end) < 360 &&
62 { 60 p.sun_longitude(t_end) > 355) {
63 time+=day; 61 time += day;
64 t=t_end; 62 t = t_end;
65 t_end=julian.getJulianKiloYear(time+day); 63 t_end = julian.getJulianKiloYear(time + day);
66 } 64 }
67 /* 循环体time每次在已经计算出的上一节气基础上前进12日,理论上春分在t_end之后 65 /* 循环体time每次在已经计算出的上一节气基础上前进12日,理论上春分在t_end之后
68 * 当跳出上一while循环时理论上春分时刻正在t与t_end之间 66 * 当跳出上一while循环时理论上春分时刻正在t与t_end之间
69 * 为保险起见,添加这个循环 67 * 为保险起见,添加这个循环
70 * 当t时刻太阳地心视黄经在[0,5]时,证明春分在前边,t和t_end后退24h 68 * 当t时刻太阳地心视黄经在[0,5]时,证明春分在前边,t和t_end后退24h
71 */ 69 */
72 while(p.sun_longitude(t)<5) 70 while (p.sun_longitude(t) < 5) {
73 { 71 time -= day;
74 time-=day; 72 t_end = t;
75 t_end=t; 73 t = julian.getJulianKiloYear(time);
76 t=julian.getJulianKiloYear(time);
77 } 74 }
78 75
79 //二分法计算春分 76 //二分法计算春分
80 while(t_end-t>delta) 77 while (t_end - t > delta) {
81 { 78 t_middle = (t + t_end) / 2;
82 t_middle=(t+t_end)/2; 79 if (p.sun_longitude(t_middle) < 360 &&
83 if(p.sun_longitude(t_middle)<360&&p.sun_longitude(t_middle)>355) 80 p.sun_longitude(t_middle) > 355) {
84 { 81 t = t_middle;
85 t=t_middle; 82 } else {
86 } 83 t_end = t_middle;
87 else
88 {
89 t_end=t_middle;
90 } 84 }
91 } 85 }
92 } 86 }
93 //其他情况 87 //其他情况
94 else 88 else {
95 {
96 //当t_end时刻太阳地心视黄经小于目标角度,节气在后,t和t_end前进24h 89 //当t_end时刻太阳地心视黄经小于目标角度,节气在后,t和t_end前进24h
97 while(p.sun_longitude(t_end)<target_angle) 90 while (p.sun_longitude(t_end) < target_angle) {
98 { 91 time += day;
99 time+=day; 92 t = t_end;
100 t=t_end; 93 t_end = julian.getJulianKiloYear(time + day);
101 t_end=julian.getJulianKiloYear(time+day);
102 } 94 }
103 95
104 //当t时刻太阳地心视黄经大于目标角度,节气在前,t和t_end后退24h 96 //当t时刻太阳地心视黄经大于目标角度,节气在前,t和t_end后退24h
105 //该循环也是一个保险循环 97 //该循环也是一个保险循环
106 while(p.sun_longitude(t)>target_angle) 98 while (p.sun_longitude(t) > target_angle) {
107 { 99 time -= day;
108 time-=day; 100 t_end = t;
109 t_end=t; 101 t = julian.getJulianKiloYear(time);
110 t=julian.getJulianKiloYear(time);
111 } 102 }
112 103
113 while(t_end-t>delta) 104 while (t_end - t > delta) {
114 { 105 t_middle = (t + t_end) / 2;
115 t_middle=(t+t_end)/2; 106 if (p.sun_longitude(t_middle) < target_angle) {
116 if(p.sun_longitude(t_middle)<target_angle) 107 t = t_middle;
117 { 108 } else {
118 t=t_middle; 109 t_end = t_middle;
119 }
120 else
121 {
122 t_end=t_middle;
123 } 110 }
124 } 111 }
125 } 112 }
126 113
127 //链表记录节气信息 114 //链表记录节气信息
128 time=julian.kiloYearToTime(t,i==0?date->tm_year+1899:date->tm_year+1900); 115 time = julian.kiloYearToTime(t, i == 0 ? date->tm_year + 1899
129 date_tmp=localtime(&time); 116 : date->tm_year + 1900);
130 list.append(date_tmp,false,true,i%2==0,i,t); 117 date_tmp = localtime(&time);
118 list.append(date_tmp, false, true, i % 2 == 0, i, t);
131 } 119 }
132} 120}
133 121
134// 用以判断朔日的函数,返回true则太阳地心黄经大于月球地心黄经,即朔日在此后 122// 用以判断朔日的函数,返回true则太阳地心黄经大于月球地心黄经,即朔日在此后
135bool date_forward(double sun_longitude,double moon_longitude) 123bool date_forward(double sun_longitude, double moon_longitude) {
136{
137 /* 判断逻辑 124 /* 判断逻辑
138 * 当moon_longitude<sun_longitude时,由于时刻已经在朔日附近 125 * 当moon_longitude<sun_longitude时,由于时刻已经在朔日附近
139 * 因而可以判断朔日在该时刻之后 126 * 因而可以判断朔日在该时刻之后
@@ -142,90 +129,84 @@ bool date_forward(double sun_longitude,double moon_longitude)
142 * 否则,大于20时候,度数相差过大,理论上只可能为moon_longitude已接近360,sun_longitude略微大于0 129 * 否则,大于20时候,度数相差过大,理论上只可能为moon_longitude已接近360,sun_longitude略微大于0
143 * 此时实际上是月亮应当追赶太阳,因而朔日在此后 130 * 此时实际上是月亮应当追赶太阳,因而朔日在此后
144 */ 131 */
145 return moon_longitude < sun_longitude ? true : (moon_longitude-sun_longitude >= 20); 132 return moon_longitude < sun_longitude
133 ? true
134 : (moon_longitude - sun_longitude >= 20);
146} 135}
147 136
148void ShuoRi(int year) 137void ShuoRi(int year) {
149{ 138 double t, t_end, end,
150 double t,t_end,end,t_middle;//采用二分法计算,t与t_end为间隔24h的两个时刻 139 t_middle; //采用二分法计算,t与t_end为间隔24h的两个时刻
151 time_t time; 140 time_t time;
152 Date* date_tmp=new Date; 141 Date *date_tmp = new Date;
153 142
154 //根据zhongqi_vec的最后一项(今年冬至)计算冬至下一日的0时刻 143 //根据zhongqi_vec的最后一项(今年冬至)计算冬至下一日的0时刻
155 date_tmp->tm_year=list.zhongqi_vec[12]->year-1900; 144 date_tmp->tm_year = list.zhongqi_vec[12]->year - 1900;
156 date_tmp->tm_mon=list.zhongqi_vec[12]->mon-1; 145 date_tmp->tm_mon = list.zhongqi_vec[12]->mon - 1;
157 date_tmp->tm_mday=list.zhongqi_vec[12]->day+1; 146 date_tmp->tm_mday = list.zhongqi_vec[12]->day + 1;
158 date_tmp->tm_hour=0; 147 date_tmp->tm_hour = 0;
159 date_tmp->tm_min=0; 148 date_tmp->tm_min = 0;
160 date_tmp->tm_sec=0; 149 date_tmp->tm_sec = 0;
161 date_tmp->tm_isdst=-1; 150 date_tmp->tm_isdst = -1;
162 time=mktime(date_tmp); 151 time = mktime(date_tmp);
163 end=julian.getJulianKiloYear(time); 152 end = julian.getJulianKiloYear(time);
164 153
165 // 计算去年冬至时刻的time 154 // 计算去年冬至时刻的time
166 date_tmp->tm_year=list.zhongqi_vec[0]->year-1900; 155 date_tmp->tm_year = list.zhongqi_vec[0]->year - 1900;
167 date_tmp->tm_mon=list.zhongqi_vec[0]->mon-1; 156 date_tmp->tm_mon = list.zhongqi_vec[0]->mon - 1;
168 date_tmp->tm_mday=list.zhongqi_vec[0]->day; 157 date_tmp->tm_mday = list.zhongqi_vec[0]->day;
169 date_tmp->tm_hour=list.zhongqi_vec[0]->hour; 158 date_tmp->tm_hour = list.zhongqi_vec[0]->hour;
170 date_tmp->tm_min=list.zhongqi_vec[0]->min; 159 date_tmp->tm_min = list.zhongqi_vec[0]->min;
171 date_tmp->tm_sec=list.zhongqi_vec[0]->sec; 160 date_tmp->tm_sec = list.zhongqi_vec[0]->sec;
172 date_tmp->tm_isdst=-1; 161 date_tmp->tm_isdst = -1;
173 time=mktime(date_tmp); 162 time = mktime(date_tmp);
174 163
175 delete date_tmp; 164 delete date_tmp;
176 165
177 // 定朔日 166 // 定朔日
178 for(t=julian.getJulianKiloYear(time);t<=end;time+=25*day) 167 for (t = julian.getJulianKiloYear(time); t <= end; time += 25 * day) {
179 {
180 // 每月长度为28-30天,因而每次循环前进25天 168 // 每月长度为28-30天,因而每次循环前进25天
181 t=julian.getJulianKiloYear(time); 169 t = julian.getJulianKiloYear(time);
182 t_end=julian.getJulianKiloYear(time+day); 170 t_end = julian.getJulianKiloYear(time + day);
183 171
184 // 太阳在月亮之前,月亮追赶,故朔日在后,t和t_end前进24h 172 // 太阳在月亮之前,月亮追赶,故朔日在后,t和t_end前进24h
185 while(date_forward(p.sun_longitude(t_end),p.moon_longitude(t_end))) 173 while (date_forward(p.sun_longitude(t_end), p.moon_longitude(t_end))) {
186 { 174 time += day;
187 time+=day; 175 t = t_end;
188 t=t_end; 176 t_end = julian.getJulianKiloYear(time + day);
189 t_end=julian.getJulianKiloYear(time+day);
190 } 177 }
191 // 太阳在月亮之后,月亮落后,故朔日在前,t和t_end后退24h(用以保险) 178 // 太阳在月亮之后,月亮落后,故朔日在前,t和t_end后退24h(用以保险)
192 while(!date_forward(p.sun_longitude(t),p.moon_longitude(t))) 179 while (!date_forward(p.sun_longitude(t), p.moon_longitude(t))) {
193 { 180 time -= day;
194 time-=day; 181 t_end = t;
195 t_end=t; 182 t = julian.getJulianKiloYear(time);
196 t=julian.getJulianKiloYear(time);
197 } 183 }
198 184
199 while(t_end-t>=delta) 185 while (t_end - t >= delta) {
200 { 186 t_middle = (t + t_end) / 2;
201 t_middle=(t+t_end)/2; 187 if (date_forward(p.sun_longitude(t_middle),
202 if(date_forward(p.sun_longitude(t_middle),p.moon_longitude(t_middle))) 188 p.moon_longitude(t_middle))) {
203 { 189 t = t_middle;
204 t=t_middle; 190 } else {
205 } 191 t_end = t_middle;
206 else
207 {
208 t_end=t_middle;
209 } 192 }
210 } 193 }
211 // 输出朔日信息 194 // 输出朔日信息
212 time=julian.kiloYearToTime(t,year-1); 195 time = julian.kiloYearToTime(t, year - 1);
213 date_tmp=localtime(&time); 196 date_tmp = localtime(&time);
214 list.append(date_tmp,true,false,false,-1,t); 197 list.append(date_tmp, true, false, false, -1, t);
215 } 198 }
216} 199}
217 200
218int main(int argc,char* argv[]) 201int main(int argc, char *argv[]) {
219{
220 202
221 if(argc!=2) 203 if (argc != 2) {
222 { 204 printf("Usage: %s year\\n\n", argv[0]);
223 printf("Usage: %s year\\n\n",argv[0]);
224 return 0; 205 return 0;
225 } 206 }
226 Date* date=input(argv[1]); 207 Date *date = input(argv[1]);
227 int year=date->tm_year+1900; 208 int year = date->tm_year + 1900;
228 double begin,end; 209 double begin, end;
229 210
230 JieQi(date); 211 JieQi(date);
231 ShuoRi(year); 212 ShuoRi(year);
@@ -240,7 +221,6 @@ int main(int argc,char* argv[])
240 221
241 // 释放内存,使用List的析构函数 222 // 释放内存,使用List的析构函数
242 223
243
244 delete date; 224 delete date;
245 225
246 return 0; 226 return 0;