pycalcal
pycalcal copied to clipboard
Maximum Date Supported
I haven't yet seen the book define the maximum date the lisp routines support. However, based on the function call result in the example below, the maximum Gregorian year should be 2938 or less (at least for the Hindu functions). Once the value is clear, it would be nice if the maximum date (or year) supported was provided by the source code.
>>> import pycalcal as pcc
>>> pcc.hindu_lunar_holiday(9, 1, 2939)
[]
The Gregorian years in ephemeris_correction
for the various bounds are much lower than 2938 (i.e., 2019 is the highest Gregorian year, in the first if statement), so the problem above is likely due to the limitations of that function. However, there may be other limitations too.
Ok, the problem above with Gregorian year 2939 is due to lunar month 9 only existing during that Gregorian year with lunar days 20-30 as shown below:
>>> pcc.hindu_lunar_from_fixed(date(2938, 12, 13).toordinal())
[2995, 9, False, 1, False]
>>> pcc.hindu_lunar_from_fixed(date(2940, 1, 1).toordinal())
[2996, 9, False, 1, False]
>>> pcc.hindu_lunar_from_fixed(date(2939, 1, 1).toordinal())
[2995, 9, False, 20, False]
>>> pcc.hindu_lunar_from_fixed(date(2939, 1, 11).toordinal())
[2995, 9, False, 30, False]
I created a general test (provided below) to ensure a conversion to a Hindu lunar date can be reversed with the same source code. So far, it looks like everything works fine up to Gregorian year 3000 at least:
#!/usr/bin/env python3
import pycalcal as pcc
from datetime import date, timedelta
if __name__ == '__main__':
done = False
year = 2019
d = date(year, 1, 1)
while not done:
if year != d.year:
year = d.year
print(year)
fixed_solar = d.toordinal()
lunar = pcc.hindu_lunar_from_fixed(fixed_solar)
lunar_month = lunar[1]
lunar_day = lunar[3]
lunar_leap = lunar[2] or lunar[4]
fixed_lunar = pcc.hindu_lunar_holiday(lunar_month, lunar_day, d.year)
valid = fixed_lunar != []
if valid:
if (fixed_solar - fixed_lunar[0]) not in frozenset((0, 1)):
valid = len(fixed_lunar) == 2 and (
(fixed_solar - fixed_lunar[1]) in frozenset((0, 1))
)
if not valid and lunar_leap:
# ignore lunar leap not matching
valid = True
elif lunar_leap:
# ignore lunar leap not matching
valid = True
if valid:
d += timedelta(days=1)
else:
print('failed at', date.fromordinal(fixed_solar),
fixed_solar, fixed_lunar, lunar)
done = True
It looks like CALENDRICA 4.0 changes are required to support the Gregorian year range -1999 to +3000, at least for the ephemeris_correction
function results. The additional modifications to the ephemeris_correction
function are from the NASA Eclipse website.
So, while nothing breaks when reversing the Hindu lunar date conversion in the script above, the accumulated error from ephemeris_correction
(and possibly other functions?) should make the maximum Gregorian year supported by CALENDRICA 3.0 less than 3000. The error should be responsible for the Hindu lunar month 9 (Agrahāyaṇa or Mārgaśīrṣa) shifting into January in the output above (month 9 should be during November/December).
To avoid the Hindu lunar month 9 shifting into January, it is best to only use Gregorian years less than 2310 (with CALENDRICA 3.0) based on the script:
#!/usr/bin/env python3
import pycalcal as pcc
from datetime import date
if __name__ == '__main__':
done = False
year = 1900
while not done:
year += 1
lunar = pcc.hindu_lunar_from_fixed(date(year, 1, 1).toordinal())
lunar_month = lunar[1]
lunar_day = lunar[3]
if lunar_month == 9:
days = [
date.fromordinal(fixed)
for fixed in pcc.hindu_lunar_holiday(lunar_month, lunar_day, year)
]
december = False
for day in days:
if day.month == 12:
december = True
break
if not december:
print(year, lunar, days)
done = True
print('years valid before', year)