1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """
24 Provide calendar to sdn (serial date number) conversion.
25 """
26
27
28
29
30
31
32 import math
33
34
35
36
37
38
39 _GRG_SDN_OFFSET = 32045
40 _GRG_DAYS_PER_5_MONTHS = 153
41 _GRG_DAYS_PER_4_YEARS = 1461
42 _GRG_DAYS_PER_400_YEARS = 146097
43
44 _JLN_SDN_OFFSET = 32083
45 _JLN_DAYS_PER_5_MONTHS = 153
46 _JLN_DAYS_PER_4_YEARS = 1461
47
48 _HBR_HALAKIM_PER_DAY = 25920
49 _HBR_HALAKIM_PER_LUNAR_CYCLE = 765433
50 _HBR_HALAKIM_PER_METONIC_CYCLE = 179876755
51 _HBR_SDN_OFFSET = 347997
52 _HBR_NEW_MOON_OF_CREATION = 31524
53 _HBR_NOON = 19440
54 _HBR_AM3_11_20 = 9924
55 _HBR_AM9_32_43 = 16789
56
57 _HBR_SUNDAY = 0
58 _HBR_MONDAY = 1
59 _HBR_TUESDAY = 2
60 _HBR_WEDNESDAY = 3
61 _HBR_FRIDAY = 5
62
63 _HBR_MONTHS_PER_YEAR = [
64 12, 12, 13, 12, 12, 13, 12, 13, 12, 12,
65 13, 12, 12, 13, 12, 12, 13, 12, 13
66 ]
67
68 _HBR_YEAR_OFFSET = [
69 0, 12, 24, 37, 49, 61, 74, 86, 99, 111, 123,
70 136, 148, 160, 173, 185, 197, 210, 222
71 ]
72
73 _FR_SDN_OFFSET = 2375474
74 _FR_DAYS_PER_4_YEARS = 1461
75 _FR_DAYS_PER_MONTH = 30
76 _PRS_EPOCH = 1948320.5
77 _ISM_EPOCH = 1948439.5
78
79 -def _tishri1(metonic_year, molad_day, molad_halakim):
80
81 tishri1 = molad_day
82 dow = tishri1 % 7
83 leap_year = metonic_year in [ 2, 5, 7, 10, 13, 16, 18]
84 last_was_leap_year = metonic_year in [ 3, 6, 8, 11, 14, 17, 0]
85
86
87 if ((molad_halakim >= _HBR_NOON) or
88 ((not leap_year) and dow == _HBR_TUESDAY and
89 molad_halakim >= _HBR_AM3_11_20) or
90 (last_was_leap_year and dow == _HBR_MONDAY
91 and molad_halakim >= _HBR_AM9_32_43)) :
92 tishri1 += 1
93 dow += 1
94 if dow == 7:
95 dow = 0
96
97
98
99 if dow == _HBR_WEDNESDAY or dow == _HBR_FRIDAY or dow == _HBR_SUNDAY:
100 tishri1 += 1
101
102 return tishri1
103
105 """
106 Estimate the metonic cycle number.
107
108 Note that this may be an under estimate because there are 6939.6896 days
109 in a metonic cycle not 6940, but it will never be an over estimate. The
110 loop below will correct for any error in this estimate.
111 """
112
113 metonic_cycle = (input_day + 310) / 6940
114
115
116
117 (molad_day, molad_halakim) = _molad_of_metonic_cycle(metonic_cycle)
118
119
120
121
122
123
124 while molad_day < (input_day - 6940 + 310):
125 metonic_cycle = metonic_cycle + 1
126 molad_halakim = molad_halakim + _HBR_HALAKIM_PER_METONIC_CYCLE
127 molad_day = molad_day + ( molad_halakim / _HBR_HALAKIM_PER_DAY)
128 molad_halakim = molad_halakim % _HBR_HALAKIM_PER_DAY
129
130
131
132 for metonic_year in range(0, 18):
133 if molad_day > input_day - 74:
134 break
135
136 molad_halakim = molad_halakim + (_HBR_HALAKIM_PER_LUNAR_CYCLE
137 * _HBR_MONTHS_PER_YEAR[metonic_year])
138 molad_day = molad_day + (molad_halakim / _HBR_HALAKIM_PER_DAY)
139 molad_halakim = molad_halakim % _HBR_HALAKIM_PER_DAY
140 else:
141 metonic_year += 1
142 return (metonic_cycle, metonic_year, molad_day, molad_halakim)
143
173
175 """
176 Calculate the start of the year.
177 """
178 metonic_cycle = (year - 1) / 19
179 metonic_year = (year - 1) % 19
180 (molad_day, molad_halakim) = _molad_of_metonic_cycle(metonic_cycle)
181
182 molad_halakim = molad_halakim + (_HBR_HALAKIM_PER_LUNAR_CYCLE
183 * _HBR_YEAR_OFFSET[metonic_year])
184 molad_day = molad_day + (molad_halakim / _HBR_HALAKIM_PER_DAY)
185 molad_halakim = molad_halakim % _HBR_HALAKIM_PER_DAY
186
187 pTishri1 = _tishri1(metonic_year, molad_day, molad_halakim)
188
189 return (metonic_cycle, metonic_year, molad_day, molad_halakim, pTishri1)
190
192 """Convert a Jewish calendar date to an SDN number."""
193
194 if month == 1 or month == 2:
195
196 (metonic_cycle, metonic_year,
197 molad_day, molad_halakim, tishri1) = _start_of_year(year)
198 if month == 1:
199 sdn = tishri1 + day - 1
200 else:
201 sdn = tishri1 + day + 29
202 elif month == 3:
203
204
205
206 (metonic_cycle, metonic_year,
207 molad_day, molad_halakim, tishri1) = _start_of_year(year)
208
209
210 molad_halakim = molad_halakim + (_HBR_HALAKIM_PER_LUNAR_CYCLE
211 *_HBR_MONTHS_PER_YEAR[metonic_year])
212 molad_day = molad_day + (molad_halakim / _HBR_HALAKIM_PER_DAY)
213 molad_halakim = molad_halakim % _HBR_HALAKIM_PER_DAY
214 tishri1_after = _tishri1((metonic_year + 1)
215 % 19, molad_day, molad_halakim)
216
217 year_length = tishri1_after - tishri1
218
219 if year_length == 355 or year_length == 385:
220 sdn = tishri1 + day + 59
221 else:
222 sdn = tishri1 + day + 58
223 elif month == 4 or month == 5 or month == 6:
224
225
226 (metonic_cycle, metonic_year,
227 molad_day, molad_halakim, tishri1_after) = _start_of_year(year+1)
228
229 if _HBR_MONTHS_PER_YEAR[(year - 1) % 19] == 12:
230 length_of_adarI_andII = 29
231 else:
232 length_of_adarI_andII = 59
233
234 if month == 4:
235 sdn = tishri1_after + day - length_of_adarI_andII - 237
236 elif month == 5:
237 sdn = tishri1_after + day - length_of_adarI_andII - 208
238 else:
239 sdn = tishri1_after + day - length_of_adarI_andII - 178
240 else:
241
242 (metonic_cycle, metonic_year,
243 molad_day, molad_halakim, tishri1_after) = _start_of_year(year+1)
244
245 if month == 7:
246 sdn = tishri1_after + day - 207
247 elif month == 8:
248 sdn = tishri1_after + day - 178
249 elif month == 9:
250 sdn = tishri1_after + day - 148
251 elif month == 10:
252 sdn = tishri1_after + day - 119
253 elif month == 11:
254 sdn = tishri1_after + day - 89
255 elif month == 12:
256 sdn = tishri1_after + day - 60
257 elif month == 13:
258 sdn = tishri1_after + day - 30
259 else:
260 return 0
261 return sdn + _HBR_SDN_OFFSET
262
264 """Convert an SDN number to a Julian calendar date."""
265
266 input_day = sdn - _HBR_SDN_OFFSET
267
268 (metonic_cycle, metonic_year, day, halakim) = _tishri_molad(input_day)
269 tishri1 = _tishri1(metonic_year, day, halakim)
270
271 if input_day >= tishri1:
272
273
274 year = (metonic_cycle * 19) + metonic_year + 1
275 if input_day < tishri1 + 59:
276 if input_day < tishri1 + 30:
277 month = 1
278 day = input_day - tishri1 + 1
279 else:
280 month = 2
281 day = input_day - tishri1 - 29
282 return (year, month, day)
283
284
285
286
287 halakim = halakim + (_HBR_HALAKIM_PER_LUNAR_CYCLE
288 * _HBR_MONTHS_PER_YEAR[metonic_year])
289 day = day + (halakim / _HBR_HALAKIM_PER_DAY)
290 halakim = halakim % _HBR_HALAKIM_PER_DAY
291 tishri1_after = _tishri1((metonic_year + 1) % 19, day, halakim)
292 else:
293
294
295 year = metonic_cycle * 19 + metonic_year
296 if input_day >= tishri1 - 177:
297
298 if input_day > tishri1 - 30:
299 month = 13
300 day = input_day - tishri1 + 30
301 elif input_day > tishri1 - 60:
302 month = 12
303 day = input_day - tishri1 + 60
304 elif input_day > tishri1 - 89:
305 month = 11
306 day = input_day - tishri1 + 89
307 elif input_day > tishri1 - 119:
308 month = 10
309 day = input_day - tishri1 + 119
310 elif input_day > tishri1 - 148:
311 month = 9
312 day = input_day - tishri1 + 148
313 else:
314 month = 8
315 day = input_day - tishri1 + 178
316 return (year, month, day)
317 else:
318 if _HBR_MONTHS_PER_YEAR[(year - 1) % 19] == 13:
319 month = 7
320 day = input_day - tishri1 + 207
321 if day > 0:
322 return (year, month, day)
323 month = month - 1
324 day = day + 30
325 if day > 0:
326 return (year, month, day)
327 month = month - 1
328 day = day + 30
329 else:
330 month = 6
331 day = input_day - tishri1 + 207
332 if day > 0:
333 return (year, month, day)
334 month = month - 1
335 day = day + 30
336
337 if day > 0:
338 return (year, month, day)
339 month = month - 1
340 day = day + 29
341 if day > 0:
342 return (year, month, day)
343
344
345
346 tishri1_after = tishri1
347 (metonic_cycle, metonic_year, day, halakim) = _tishri_molad(day-365)
348 tishri1 = _tishri1(metonic_year, day, halakim)
349
350 year_length = tishri1_after - tishri1
351 cday = input_day - tishri1 - 29
352 if year_length == 355 or year_length == 385 :
353
354 if day <= 30:
355 month = 2
356 day = cday
357 return (year, month, day)
358 day = day - 30
359 else:
360
361 if day <= 29:
362 month = 2
363 day = cday
364 return (year, month, day)
365
366 cday = cday - 29
367
368
369 return (year, 3, cday)
370
372 """Convert a Julian calendar date to an SDN number."""
373
374 if year < 0:
375 year += 4801
376 else:
377 year += 4800
378
379
380 if month > 2:
381 month -= 3
382 else:
383 month += 9
384 year -= 1
385
386 return (year * _JLN_DAYS_PER_4_YEARS)/4 \
387 + (month * _JLN_DAYS_PER_5_MONTHS+2)/5 \
388 + day - _JLN_SDN_OFFSET
389
416
436
466
472
481
483 """Convert a Persian date to an SDN number."""
484 if year >= 0:
485 epbase = year - 474
486 else:
487 epbase = year - 473
488
489 epyear = 474 + epbase % 2820
490
491 if month <= 7:
492 v1 = (month - 1) * 31
493 else:
494 v1 = ((month - 1) * 30) + 6
495 v2 = math.floor(((epyear * 682) - 110) / 2816)
496 v3 = (epyear - 1) * 365 + day
497 v4 = math.floor(epbase / 2820) * 1029983
498
499 return int(math.ceil(v1 + v2 + v3 + v4 + _PRS_EPOCH - 1))
500
502 """Convert an SDN number to a Persian calendar date."""
503 sdn = math.floor(sdn) + 0.5
504
505 depoch = sdn - 2121446
506 cycle = math.floor(depoch / 1029983)
507 cyear = depoch % 1029983
508 if cyear == 1029982:
509 ycycle = 2820
510 else:
511 aux1 = math.floor(cyear / 366)
512 aux2 = cyear % 366
513 ycycle = math.floor(((2134*aux1)+(2816*aux2)+2815)/1028522) + aux1 + 1
514
515 year = ycycle + (2820 * cycle) + 474
516 if year <= 0:
517 year = year - 1
518
519 yday = sdn - persian_sdn(year, 1, 1) + 1
520 if yday < 186:
521 month = math.ceil(yday / 31)
522 else:
523 month = math.ceil((yday - 6) / 30)
524 day = (sdn - persian_sdn(year, month, 1)) + 1
525 return (int(year), int(month), int(day))
526
528 """Convert an Islamic date to an SDN number."""
529 v1 = math.ceil(29.5 * (month - 1))
530 v2 = (year - 1) * 354
531 v3 = math.floor((3 + (11 *year)) / 30)
532
533 return int(math.ceil((day + v1 + v2 + v3 + _ISM_EPOCH) - 1))
534
536 """Convert an SDN number to an Islamic calendar date."""
537 sdn = math.floor(sdn) + 0.5
538 year = int(math.floor(((30*(sdn-_ISM_EPOCH))+10646)/10631))
539 month = int(min(12, math.ceil((sdn-(29+islamic_sdn(year, 1, 1)))/29.5) + 1))
540 day = int((sdn - islamic_sdn(year, month, 1)) + 1)
541 return (year, month, day)
542