- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPythonEaster.py
More file actions
Latest commit
199 lines (161 loc) · 6.58 KB
/
Copy pathPythonEaster.py
File metadata and controls
199 lines (161 loc) · 6.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/usr/bin/env python
iMIN_VERSION=3#Minimum version of the Python for this script.
importos
importsys
importdatetime
##Globals for the Easter functions
iEDM_JULIAN=1
iEDM_ORTHODOX=2
iEDM_WESTERN=3
iFIRST_EASTER_YEAR=326
iFIRST_VALID_GREGORIAN_YEAR=1583
iLAST_VALID_GREGORIAN_YEAR=4099
defxRunningCorrectPythonVersion(sMinimumVersion='3'):
'''Assumes a version number returned from the system in a format similar to: '3.2.1' .
We can check against (major), (major and minor), or (major, minor, and micro) release levels.
The default minimum is a major release level of '3' .
Input of type Integer or Long is converted to type String.
Return value: True or False, whether the version is sufficient.
'''
importplatform
#Find length of version requested.
# The length can be between 1 and 5, e.g. between a version like '3' and '3.2.1' .
#Cast input as string, in case an integer has been passed.
sMinVer=str(sMinimumVersion)
iVerLen=len(sMinVer)
if (iVerLen<1) or (iVerLen>5):
raiseValueError('Release levels of 1 - 5 characters in length, only, are valid: e.g. \'3\' to \'3.2.1\' .')
#Find the version of Python interpreting this script
sPythonVersion=platform.python_version()
#Check major release level
ifint(sPythonVersion[:1]) <int(sMinVer[:1]):
returnFalse
#Check minor release level
iflen(sMinVer) >2:
ifint(sPythonVersion[2:3]) <int(sMinVer[2:3]):
returnFalse
#Check micro release level
iflen(sMinVer) >4:
ifint(sPythonVersion[4:5]) <int(sMinVer[4:5]):
returnFalse
#Having passed all checks, we are OK.
returnTrue
defpF15_CalcDateOfEaster(iYearToFind, iDatingMethod):
# default values for invalid arguments
imDay=0
imMonth=0
# intermediate results (all integers)
iFirstDig=0
iRemain19=0
iTempNum=0
# tables A to E results (all integers)
iTableA=0
iTableB=0
iTableC=0
iTableD=0
iTableE=0
# Calculate Easter Sunday date
# first 2 digits of year (integer division)
iFirstDig=iYearToFind//100
# remainder of year / 19
iRemain19=iYearToFind%19
if (iDatingMethod==iEDM_JULIAN) or (iDatingMethod==iEDM_ORTHODOX):
# calculate PFM date
iTableA= ((225-11*iRemain19) %30) +21
# find the next Sunday
iTableB= (iTableA-19) %7
iTableC= (40-iFirstDig) %7
iTempNum=iYearToFind%100
iTableD= (iTempNum+ (iTempNum//4)) %7
iTableE= ((20-iTableB-iTableC-iTableD) %7) +1
imDay=iTableA+iTableE
# convert Julian to Gregorian date
ifiDatingMethod==iEDM_ORTHODOX:
# 10 days were # skipped# in the Gregorian calendar from 5-14 Oct 1582
iTempNum=10
# Only 1 in every 4 century years are leap years in the Gregorian
# calendar (every century is a leap year in the Julian calendar)
ifiYearToFind>1600 :
iTempNum=iTempNum+iFirstDig-16- ((iFirstDig-16) //4)
imDay=imDay+iTempNum
else:
#That is iDatingMethod == iEDM_WESTERN
# calculate PFM date
iTempNum= ((iFirstDig-15) //2) +202-11*iRemain19
lFirstList= [21, 24, 25, 27, 28, 29, 30, 31, 32, 34, 35, 38]
lSecondList= [33, 36, 37, 39, 40]
ifiFirstDiginlFirstList:
iTempNum=iTempNum-1
elifiFirstDiginlSecondList:
iTempNum=iTempNum-2
iTempNum=iTempNum%30
iTableA=iTempNum+21
ifiTempNum==29 :
iTableA=iTableA-1
if ((iTempNum==28) and (iRemain19>10)):
iTableA=iTableA-1
# find the next Sunday
iTableB= (iTableA-19) %7
iTableC= (40-iFirstDig) %4
ifiTableC==3 :
iTableC=iTableC+1
ifiTableC>1 :
iTableC=iTableC+1
iTempNum=iYearToFind%100
iTableD= (iTempNum+iTempNum//4) %7
iTableE= ((20-iTableB-iTableC-iTableD) %7) +1
imDay=iTableA+iTableE
# return the date
ifimDay>61 :
imDay=imDay-61
imMonth=5
# for imMethod 2, Easter Sunday can occur in May
elifimDay>31 :
imDay=imDay-31
imMonth=4
else:
imMonth=3
returndatetime.date(iYearToFind, imMonth, imDay)
defmain(argv):
#Check two arguments: year and dating method, the second of which is optional
if (len(argv) >3) or (len(argv) <1):
sys.stderr.write("USAGE: %s <year, in which the date of Easter is sought> ?<dating method; Western/Gregorian is the default>? \n"% (argv[0]))
returnNone
eliflen(argv) ==1:
sYearToFind=datetime.date.today().strftime('%Y')
sDatingMethod=str(iEDM_WESTERN)
eliflen(argv) ==3:
sYearToFind=argv[1]
sDatingMethod=argv[2]
else:
#That is: len(argv) == 2:
sYearToFind=argv[1]
sDatingMethod=None
ifsDatingMethodisNone:
sDatingMethod=str(iEDM_WESTERN)
#Confirm that the arguments are valid
try:
iYearToFind=int(sYearToFind)
exceptException:
sys.stderr.write("The first argument should be the year, for which the data of Easter is sought.")
returnNone
try:
iDatingMethod=int(sDatingMethod)
exceptException:
sys.stderr.write("The second argument is the dating method: 1, 2, or 3.")
returnNone
if (iDatingMethod<iEDM_JULIAN) or (iDatingMethod>iEDM_WESTERN):
sys.stderr.write("The dating method must be 1, 2, or 3. You used: %s .\n"%sDatingMethod)
returnNone
if (iYearToFind<iFIRST_EASTER_YEAR) or (iYearToFind>iLAST_VALID_GREGORIAN_YEAR):
sys.stderr.write("The year requested is not valid. You used: %s .\n"%sYearToFind)
returnNone
#Find the date of Easter
dEasterDate=pF15_CalcDateOfEaster(iYearToFind, iDatingMethod)
print(dEasterDate.strftime("%Y-%m-%d -OR- %d %B %Y"))
if__name__=="__main__":
#Initially, check that we are running the correct version of the Python interpreter.
ifnotxRunningCorrectPythonVersion(iMIN_VERSION):
sys.exit('The minimum version of Python required is: '+str(iMIN_VERSION) +' .')
#The main procedure accesses the web pages or files, based on the arguments supplied.
sys.exit(main(sys.argv))