jpayne@69
|
1 # -*- coding: utf-8 -*-
|
jpayne@69
|
2 """
|
jpayne@69
|
3 This module offers a generic Easter computing method for any given year, using
|
jpayne@69
|
4 Western, Orthodox or Julian algorithms.
|
jpayne@69
|
5 """
|
jpayne@69
|
6
|
jpayne@69
|
7 import datetime
|
jpayne@69
|
8
|
jpayne@69
|
9 __all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"]
|
jpayne@69
|
10
|
jpayne@69
|
11 EASTER_JULIAN = 1
|
jpayne@69
|
12 EASTER_ORTHODOX = 2
|
jpayne@69
|
13 EASTER_WESTERN = 3
|
jpayne@69
|
14
|
jpayne@69
|
15
|
jpayne@69
|
16 def easter(year, method=EASTER_WESTERN):
|
jpayne@69
|
17 """
|
jpayne@69
|
18 This method was ported from the work done by GM Arts,
|
jpayne@69
|
19 on top of the algorithm by Claus Tondering, which was
|
jpayne@69
|
20 based in part on the algorithm of Ouding (1940), as
|
jpayne@69
|
21 quoted in "Explanatory Supplement to the Astronomical
|
jpayne@69
|
22 Almanac", P. Kenneth Seidelmann, editor.
|
jpayne@69
|
23
|
jpayne@69
|
24 This algorithm implements three different Easter
|
jpayne@69
|
25 calculation methods:
|
jpayne@69
|
26
|
jpayne@69
|
27 1. Original calculation in Julian calendar, valid in
|
jpayne@69
|
28 dates after 326 AD
|
jpayne@69
|
29 2. Original method, with date converted to Gregorian
|
jpayne@69
|
30 calendar, valid in years 1583 to 4099
|
jpayne@69
|
31 3. Revised method, in Gregorian calendar, valid in
|
jpayne@69
|
32 years 1583 to 4099 as well
|
jpayne@69
|
33
|
jpayne@69
|
34 These methods are represented by the constants:
|
jpayne@69
|
35
|
jpayne@69
|
36 * ``EASTER_JULIAN = 1``
|
jpayne@69
|
37 * ``EASTER_ORTHODOX = 2``
|
jpayne@69
|
38 * ``EASTER_WESTERN = 3``
|
jpayne@69
|
39
|
jpayne@69
|
40 The default method is method 3.
|
jpayne@69
|
41
|
jpayne@69
|
42 More about the algorithm may be found at:
|
jpayne@69
|
43
|
jpayne@69
|
44 `GM Arts: Easter Algorithms <http://www.gmarts.org/index.php?go=415>`_
|
jpayne@69
|
45
|
jpayne@69
|
46 and
|
jpayne@69
|
47
|
jpayne@69
|
48 `The Calendar FAQ: Easter <https://www.tondering.dk/claus/cal/easter.php>`_
|
jpayne@69
|
49
|
jpayne@69
|
50 """
|
jpayne@69
|
51
|
jpayne@69
|
52 if not (1 <= method <= 3):
|
jpayne@69
|
53 raise ValueError("invalid method")
|
jpayne@69
|
54
|
jpayne@69
|
55 # g - Golden year - 1
|
jpayne@69
|
56 # c - Century
|
jpayne@69
|
57 # h - (23 - Epact) mod 30
|
jpayne@69
|
58 # i - Number of days from March 21 to Paschal Full Moon
|
jpayne@69
|
59 # j - Weekday for PFM (0=Sunday, etc)
|
jpayne@69
|
60 # p - Number of days from March 21 to Sunday on or before PFM
|
jpayne@69
|
61 # (-6 to 28 methods 1 & 3, to 56 for method 2)
|
jpayne@69
|
62 # e - Extra days to add for method 2 (converting Julian
|
jpayne@69
|
63 # date to Gregorian date)
|
jpayne@69
|
64
|
jpayne@69
|
65 y = year
|
jpayne@69
|
66 g = y % 19
|
jpayne@69
|
67 e = 0
|
jpayne@69
|
68 if method < 3:
|
jpayne@69
|
69 # Old method
|
jpayne@69
|
70 i = (19*g + 15) % 30
|
jpayne@69
|
71 j = (y + y//4 + i) % 7
|
jpayne@69
|
72 if method == 2:
|
jpayne@69
|
73 # Extra dates to convert Julian to Gregorian date
|
jpayne@69
|
74 e = 10
|
jpayne@69
|
75 if y > 1600:
|
jpayne@69
|
76 e = e + y//100 - 16 - (y//100 - 16)//4
|
jpayne@69
|
77 else:
|
jpayne@69
|
78 # New method
|
jpayne@69
|
79 c = y//100
|
jpayne@69
|
80 h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30
|
jpayne@69
|
81 i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11))
|
jpayne@69
|
82 j = (y + y//4 + i + 2 - c + c//4) % 7
|
jpayne@69
|
83
|
jpayne@69
|
84 # p can be from -6 to 56 corresponding to dates 22 March to 23 May
|
jpayne@69
|
85 # (later dates apply to method 2, although 23 May never actually occurs)
|
jpayne@69
|
86 p = i - j + e
|
jpayne@69
|
87 d = 1 + (p + 27 + (p + 6)//40) % 31
|
jpayne@69
|
88 m = 3 + (p + 26)//30
|
jpayne@69
|
89 return datetime.date(int(y), int(m), int(d))
|