default to AA for years outside 1901-2100

This commit is contained in:
Chen Wei
2014-03-11 10:37:30 +08:00
parent b273c986e1
commit 996520bc41
5 changed files with 155 additions and 80 deletions

4
aa.py
View File

@@ -1,6 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__license__ = 'BSD'
__copyright__ = '2014, Chen Wei <weichen302@gmail.com>'
__version__ = '0.0.3'
from numpy import *
import numexpr as ne
import re

View File

@@ -1,6 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__license__ = 'BSD'
__copyright__ = '2014, Chen Wei <weichen302@gmail.com>'
__version__ = '0.0.3'
from numpy import *
import numexpr as ne
from aa_full_table import *

View File

@@ -1,12 +1,16 @@
__license__ = 'BSD'
__copyright__ = '2014, Chen Wei <weichen302@gmail.com>'
__version__ = '0.0.3'
from numpy import array
# table for LEA-406 moon solution. Those terms are linear combination
# of integer multipliers of 14 variables (Arg_j_, j=1,14):
# Delaunay variables l, l', F, D;
# mean longitude of the ascending node of the Moon {Omega};
# mean longitudes of eight major planets {lambda}_pl_;
# and the general precession in longitude p_A_.
# terms of 3rd-degree and 4th-degree are ignored
# in arcsec
M_ARG = array([
# 10508 terms

View File

@@ -10,7 +10,7 @@ lunar calendar data from their website.
__license__ = 'BSD'
__copyright__ = '2014, Chen Wei <weichen302@gmail.com>'
__version__ = '0.0.2'
__version__ = '0.0.3'
from StringIO import StringIO
from datetime import datetime
@@ -24,11 +24,13 @@ import sqlite3
import sys
import urllib2
import zlib
from lunarcalbase import cn_lunarcal
APPDIR = os.path.abspath(os.path.dirname(__file__))
DB_FILE = os.path.join(APPDIR, 'db', 'lunarcal.sqlite')
RE_CAL = re.compile(u'(\d{4})年(\d{1,2})月(\d{1,2})日')
PROXY = {'http': 'http://localhost:8001'}
#PROXY = {'http': 'http://localhost:8001'}
PROXY = None
URL = 'http://data.weather.gov.hk/gts/time/calendar/text/T%dc.txt'
OUTPUT = os.path.join(APPDIR, 'chinese_lunar_%s_%s.ics')
@@ -93,6 +95,15 @@ def initdb():
db.close()
def printjieqi():
sql = 'select jieqi from ical where jieqi NOT NULL limit 28'
res = query_db(sql)
d = -75
for row in res:
print "%d: u'%s', " % (d, row[0])
d += 15
def query_db(query, args=(), one=False):
''' wrap the db query, fetch into one step '''
conn = sqlite3.connect(DB_FILE)
@@ -193,10 +204,22 @@ def gen_cal(start, end, fp):
Return:
none
'''
startyear = int(start[:4])
endyear = int(end[:4])
if startyear > 1900 and endyear < 2101:
# use Lunar Calendar from HKO
print 'use Lunar Calendar from HKO'
sql = ('select date, lunardate, holiday, jieqi from ical '
'where date>=? and date<=? order by date')
rows = query_db(sql, (start, end))
else:
# compute Lunar Calendar by astronomical algorithm
print 'compute Lunar Calendar by astronomical algorithm '
rows = []
for year in xrange(startyear, endyear + 1):
row = cn_lunarcal(year)
rows.extend(row)
sql = ('select date, lunardate, holiday, jieqi from ical '
'where date>=? and date<=? order by date')
rows = query_db(sql, (start, end))
lines = [ICAL_HEAD]
oneday = timedelta(days=1)
for r in rows:
@@ -342,17 +365,11 @@ def main():
print str(err)
print helpmsg
sys.exit(2)
hkstart = datetime.strptime('1901-01-01', '%Y-%m-%d')
hkend = datetime.strptime('2100-12-31', '%Y-%m-%d')
for o, v in opts:
if o == '--start':
start = v
if datetime.strptime(start, '%Y-%m-%d') < hkstart:
sys.exit('start date must newer than 1901-01-01')
elif o == '--end':
end = v
if datetime.strptime(end, '%Y-%m-%d') > hkend:
sys.exit('end date must before 2100-12-31')
elif 'h' in o:
sys.exit(helpmsg)
@@ -369,5 +386,36 @@ def main():
gen_cal(start, end, fp)
def verify_lunarcalendar():
''' verify lunar calendar against data from HKO'''
start = 1949
sql = 'select date, lunardate,jieqi from ical where date>=? and date<=?'
while start < 2101:
print 'compare %d' % start
ystart = '%d-01-01' % start
yend = '%d-12-31' % start
res = query_db(sql, (ystart, yend))
hko = []
for x in res:
if x[2]:
hko.append((x[0], '%s %s' % (x[1], x[2])))
else:
hko.append((x[0], x[1]))
aalc = cn_lunarcal(start)
if start == 1900:
for x in aalc:
print x[0], x[1]
for i in xrange(len(aalc)):
aaday, aaldate = aalc[i]
hkoday, hkoldate = hko[i]
#print aaday, aaldate
if aaday != hkoday or aaldate != hkoldate:
print 'AA %s %s, HKO %s %s' % (aaday, aaldate, hkoday,
hkoldate)
start += 1
if __name__ == "__main__":
main()
#verify_lunarcalendar()

View File

@@ -1,6 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__license__ = 'BSD'
__copyright__ = '2014, Chen Wei <weichen302@gmail.com>'
__version__ = '0.0.3'
from aa_full import findnewmoons
from aa_full import solarterm
from aa_full import jdftime
@@ -48,6 +52,12 @@ CN_SOLARTERM = {-120: u'小雪',-105: u'大雪',
225: u'立冬', 240: u'小雪', 255: u'大雪', 270: u'冬至'}
# calendar for this and next year are combined to generate the final output
# cache the intermedia calendar
CALCACHE = {'cached': []}
MAXCACHE = 500 # max cached items
def find_astro(year):
''' find new moons and solar terms needed for calculate lunar calender
Arg:
@@ -59,7 +69,6 @@ def find_astro(year):
placeholder for month }, ... ]
'''
# find all solar terms from -120 to +270 degree, negative angle means
# search backward from Vernal Equinox
solarterms = []
@@ -87,71 +96,61 @@ def find_astro(year):
def mark_lunarcal_month(clc):
''' scan and modify the Chinese Lunar Calendar Astro list for start/end of
Chinese Lunar year and leapmonth'''
nmcount = 0
mname = -1
leapyear = False
i = 0
# debug
#for x in clc:
# print jdftime(x['date']), x['astro']
# scan last and this Winter Solstice
for d in clc:
if d['astro'] == -90:
lastws = d['date']
elif d['astro'] == 270:
lcend = d['date']
break
# mark month number of newmoon
while i < len(clc):
if clc[i]['month'] is None and clc[i]['astro'] == 'newmoon':
nmcount += 1
mname += 1
clc[i]['month'] = mname
elif clc[i]['astro'] == -90:
nmcount = 0
mname = LCSTARTMONTH
clc[i]['month'] = LCSTARTMONTH
if (clc[i + 1]['astro'] == 'newmoon' and
clc[i + 1]['date'] == clc[i]['date']):
# the next newmoon is the same day, it will be the day 1 of
# month 11. This newmoon doesn't included in leap year
# compute.
clc[i + 1]['month'] = LCSTARTMONTH
lcstart = clc[i]['date']
else:
n = i - 1
while n >= 0:
if clc[n]['astro'] == 'newmoon':
clc[n]['month'] = LCSTARTMONTH
lcstart = clc[n]['date']
break
n -= 1
elif clc[i]['astro'] == 270:
# lunar calendar year ends with Winter Solstice
lcend = clc[i]['date']
# the newmoon contains last Winter Solstice marks start of CLC year
for d in clc:
if d['date'] <= lastws and d['astro'] == 'newmoon':
lcstart = d['date']
elif d['date'] > lastws:
break
for d in clc[i + 1:]:
if d['date'] == clc[i]['date'] and d['astro'] == 'newmoon':
nmcount += 1
break
# if there are more than 12 newmoons between two Winter
# Solstice, it is a leap year
if nmcount > 12:
leapyear = True
i += 1
# mark month name, 11 is the month contains Winter Solstice
newmoondate = [d['date'] for d in clc if d['astro'] == 'newmoon']
mname = 11
for i in xrange(len(newmoondate) - 1):
thisnm, nextnm = newmoondate[i], newmoondate[i + 1]
if thisnm < lcstart:
continue
# mark month number for rest of days
mname = -1
for i in xrange(len(clc)):
if clc[i]['month']:
mname = clc[i]['month']
if i > 0 and clc[i - 1]['date'] == clc[i]['date']:
clc[i - 1]['month'] = mname
else:
clc[i]['month'] = mname
for d in clc:
if thisnm <= d['date'] and d['date'] < nextnm:
d['month'] = mname
elif d['date'] >= nextnm:
break
mname += 1
# trim to days between the newmoon mark the month last Winter Solstice
# belongs, to this Winter Solstice(including)
# trim to days between two Winter Solstice
clc = [d for d in clc if d['date'] >= lcstart and d['date'] <= lcend]
return scan_leap(clc)
def scan_leap(clc):
''' scan and change month name(number) if necessary
Arg:
clc: the astros trimmed to a CLC year
Return:
the Chinese Lunar Calendar astro with month name adjusted for leap
'''
lcstart, lcend = clc[0]['date'], clc[-1]['date']
# scan for leap month
leap = None
if leapyear:
nmcount = 0
for d in clc:
if (d['date'] > lcstart and d['date'] <= lcend and
d['astro'] == 'newmoon'):
nmcount += 1
# leap year has more than 12 newmoons between two Winter Solstice
if nmcount > 12:
# search leap month from LC 11, to next LC 11, which = 11 + 13
for m in xrange(11, 25):
foundleap = True
@@ -161,13 +160,13 @@ def mark_lunarcal_month(clc):
if d['month'] == m and d['astro'] % 30 == 0:
foundleap = False
if foundleap:
leap = m
monthofleap = m
break
for d in clc:
if d['month'] == leap:
if d['month'] == monthofleap:
d['month'] += -1 + 100 # add 100 to distinguish leap month
elif d['month'] > leap:
elif d['month'] > monthofleap:
d['month'] -= 1
for d in clc:
@@ -187,12 +186,15 @@ def search_lunarcal(year):
start at last LC November
'''
global CALCACHE
if year in CALCACHE:
return CALCACHE[year]
clc = find_astro(year)
clcmonth = mark_lunarcal_month(clc)
ystart = clcmonth[0]['date']
yend = clcmonth[-1]['date'] + 1
#debug
#print
#for x in clcmonth:
@@ -246,6 +248,12 @@ def search_lunarcal(year):
output[ystart] = label
ystart += 1
CALCACHE[year] = output # cache it for future use
CALCACHE['cached'].append(year)
if len(CALCACHE['cached']) > MAXCACHE:
del CALCACHE[CALCACHE['cached'][0]]
CALCACHE['cached'].pop(0)
return output
@@ -274,15 +282,22 @@ def cn_lunarcal(year):
jdftime(jd, '%y-%m-%d', ut=False),
mname))
lc.sort()
return lc
# convert to format that accepted by ical generator
rows = []
for x in lc:
rows.append({'date': x[0], 'lunardate': x[1],
'holiday': None, 'jieqi': None})
#sql = ('select date, lunardate, holiday, jieqi from ical '
return rows
def main():
#a = cn_lunarcal(2033)
#for x in a:
#print x[0], x[1]
find_astro(1979)
find_astro(2057)
a = cn_lunarcal(2033)
for x in a:
print x['date'], x['lunardate']
if __name__ == "__main__":
main()