diff options
Diffstat (limited to 'src/calendar.cpp')
-rw-r--r-- | src/calendar.cpp | 250 |
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规定之量*/ |
7 | double pi=3.14159265358979323846; | 7 | double pi = 3.14159265358979323846; |
8 | double day=86400; | 8 | double day = 86400; |
9 | double delta=1e-11; | 9 | double delta = 1e-11; |
10 | char jieqi[25][10]={"冬至","小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"}; | 10 | char jieqi[25][10] = {"冬至", "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", |
11 | "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", | ||
12 | "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", | ||
13 | "立冬", "小雪", "大雪", "冬至"}; | ||
11 | 14 | ||
12 | /*计算需要用的类的实例化*/ | 15 | /*计算需要用的类的实例化*/ |
13 | Julian julian; | 16 | Julian julian; |
14 | parameter p; | 17 | parameter p; |
15 | List list; | 18 | List list; |
16 | 19 | ||
17 | 20 | Date *input(char *argv) { | |
18 | Date* 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 | /*计算当年二十四节气时刻,自去年冬至到本年冬至*/ |
34 | void JieQi(Date* date) | 35 | void 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则太阳地心黄经大于月球地心黄经,即朔日在此后 |
135 | bool date_forward(double sun_longitude,double moon_longitude) | 123 | bool 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 | ||
148 | void ShuoRi(int year) | 137 | void 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 | ||
218 | int main(int argc,char* argv[]) | 201 | int 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; |