python万年历差农历程序_公历转农历的python实现

1 #lunar.py

2 # 2015/02/27 罗兵

3 importdatetime4

5 classLunar(object):6 #******************************************************************************

7 #下面为阴历计算所需的数据,为节省存储空间,所以采用下面比较变态的存储方法.

8 #******************************************************************************

9 #数组g_lunar_month_day存入阴历1901年到2050年每年中的月天数信息,

10 #阴历每月只能是29或30天,一年用12(或13)个二进制位表示,对应位为1表30天,否则为29天

11 g_lunar_month_day =[12 0x4ae0, 0xa570, 0x5268, 0xd260, 0xd950, 0x6aa8, 0x56a0, 0x9ad0, 0x4ae8, 0x4ae0, #1910

13 0xa4d8, 0xa4d0, 0xd250, 0xd548, 0xb550, 0x56a0, 0x96d0, 0x95b0, 0x49b8, 0x49b0, #1920

14 0xa4b0, 0xb258, 0x6a50, 0x6d40, 0xada8, 0x2b60, 0x9570, 0x4978, 0x4970, 0x64b0, #1930

15 0xd4a0, 0xea50, 0x6d48, 0x5ad0, 0x2b60, 0x9370, 0x92e0, 0xc968, 0xc950, 0xd4a0, #1940

16 0xda50, 0xb550, 0x56a0, 0xaad8, 0x25d0, 0x92d0, 0xc958, 0xa950, 0xb4a8, 0x6ca0, #1950

17 0xb550, 0x55a8, 0x4da0, 0xa5b0, 0x52b8, 0x52b0, 0xa950, 0xe950, 0x6aa0, 0xad50, #1960

18 0xab50, 0x4b60, 0xa570, 0xa570, 0x5260, 0xe930, 0xd950, 0x5aa8, 0x56a0, 0x96d0, #1970

19 0x4ae8, 0x4ad0, 0xa4d0, 0xd268, 0xd250, 0xd528, 0xb540, 0xb6a0, 0x96d0, 0x95b0, #1980

20 0x49b0, 0xa4b8, 0xa4b0, 0xb258, 0x6a50, 0x6d40, 0xada0, 0xab60, 0x9370, 0x4978, #1990

21 0x4970, 0x64b0, 0x6a50, 0xea50, 0x6b28, 0x5ac0, 0xab60, 0x9368, 0x92e0, 0xc960, #2000

22 0xd4a8, 0xd4a0, 0xda50, 0x5aa8, 0x56a0, 0xaad8, 0x25d0, 0x92d0, 0xc958, 0xa950, #2010

23 0xb4a0, 0xb550, 0xb550, 0x55a8, 0x4ba0, 0xa5b0, 0x52b8, 0x52b0, 0xa930, 0x74a8, #2020

24 0x6aa0, 0xad50, 0x4da8, 0x4b60, 0x9570, 0xa4e0, 0xd260, 0xe930, 0xd530, 0x5aa0, #2030

25 0x6b50, 0x96d0, 0x4ae8, 0x4ad0, 0xa4d0, 0xd258, 0xd250, 0xd520, 0xdaa0, 0xb5a0, #2040

26 0x56d0, 0x4ad8, 0x49b0, 0xa4b8, 0xa4b0, 0xaa50, 0xb528, 0x6d20, 0xada0, 0x55b0, #2050

27 ]28

29 #数组gLanarMonth存放阴历1901年到2050年闰月的月份,如没有则为0,每字节存两年

30 g_lunar_month =[31 0x00, 0x50, 0x04, 0x00, 0x20, #1910

32 0x60, 0x05, 0x00, 0x20, 0x70, #1920

33 0x05, 0x00, 0x40, 0x02, 0x06, #1930

34 0x00, 0x50, 0x03, 0x07, 0x00, #1940

35 0x60, 0x04, 0x00, 0x20, 0x70, #1950

36 0x05, 0x00, 0x30, 0x80, 0x06, #1960

37 0x00, 0x40, 0x03, 0x07, 0x00, #1970

38 0x50, 0x04, 0x08, 0x00, 0x60, #1980

39 0x04, 0x0a, 0x00, 0x60, 0x05, #1990

40 0x00, 0x30, 0x80, 0x05, 0x00, #2000

41 0x40, 0x02, 0x07, 0x00, 0x50, #2010

42 0x04, 0x09, 0x00, 0x60, 0x04, #2020

43 0x00, 0x20, 0x60, 0x05, 0x00, #2030

44 0x30, 0xb0, 0x06, 0x00, 0x50, #2040

45 0x02, 0x07, 0x00, 0x50, 0x03 #2050

46 ]47

48 START_YEAR = 1901

49

50 #天干

51 gan = '甲乙丙丁戊己庚辛壬癸'

52 #地支

53 zhi = '子丑寅卯辰巳午未申酉戌亥'

54 #生肖

55 xiao = '鼠牛虎兔龙蛇马羊猴鸡狗猪'

56 #月份

57 lm = '正二三四五六七八九十冬腊'

58 #日份

59 ld = '初一初二初三初四初五初六初七初八初九初十十一十二十三十四十五十六十七十八十九二十廿一廿二廿三廿四廿五廿六廿七廿八廿九三十'

60 #节气

61 jie = '小寒大寒立春雨水惊蛰春分清明谷雨立夏小满芒种夏至小暑大暑立秋处暑白露秋分寒露霜降立冬小雪大雪冬至'

62

63 def __init__(self, dt =None):64 '''初始化:参数为datetime.datetime类实例,默认当前时间'''

65 self.localtime = dt if dt elsedatetime.datetime.today()66

67 def sx_year(self): #返回生肖年

68 ct = self.localtime #取当前时间

69

70 year = self.ln_year() - 3 - 1 #农历年份减3 (说明:补减1)

71 year = year % 12 #模12,得到地支数

72 returnself.xiao[year]73

74 def gz_year(self): #返回干支纪年

75 ct = self.localtime #取当前时间

76 year = self.ln_year() - 3 - 1 #农历年份减3 (说明:补减1)

77 G = year % 10 #模10,得到天干数

78 Z = year % 12 #模12,得到地支数

79 return self.gan[G] +self.zhi[Z]80

81 def gz_month(self): #返回干支纪月(未实现)

82 pass

83

84 def gz_day(self): #返回干支纪日

85 ct = self.localtime #取当前时间

86 C = ct.year // 100 #取世纪数,减一

87 y = ct.year % 100 #取年份后两位(若为1月、2月则当前年份减一)

88 y = y - 1 if ct.month == 1 or ct.month == 2 elsey89 M = ct.month #取月份(若为1月、2月则分别按13、14来计算)

90 M = M + 12 if ct.month == 1 or ct.month == 2 elseM91 d = ct.day #取日数

92 i = 0 if ct.month % 2 == 1 else 6 #取i (奇数月i=0,偶数月i=6)

93

94 #下面两个是网上的公式

95 #http://baike.baidu.com/link?url=MbTKmhrTHTOAz735gi37tEtwd29zqE9GJ92cZQZd0X8uFO5XgmyMKQru6aetzcGadqekzKd3nZHVS99rewya6q

96 #计算干(说明:补减1)

97 G = 4 * C + C // 4 + 5 * y + y // 4 + 3 * (M + 1) // 5 + d - 3 - 1

98 G = G % 10

99 #计算支(说明:补减1)

100 Z = 8 * C + C // 4 + 5 * y + y // 4 + 3 * (M + 1) // 5 + d + 7 + i - 1

101 Z = Z % 12

102

103 #返回 干支纪日

104 return self.gan[G] +self.zhi[Z]105

106 def gz_hour(self): #返回干支纪时(时辰)

107 ct = self.localtime #取当前时间

108 #计算支

109 Z = round((ct.hour/2) + 0.1) % 12 #之所以加0.1是因为round的bug!!

110

111 #返回 干支纪时(时辰)

112 returnself.zhi[Z]113

114 def ln_year(self): #返回农历年

115 year, _, _ =self.ln_date()116 returnyear117

118 def ln_month(self): #返回农历月

119 _, month, _ =self.ln_date()120 returnmonth121

122 def ln_day(self): #返回农历日

123 _, _, day =self.ln_date()124 returnday125

126 def ln_date(self): #返回农历日期整数元组(年、月、日)(查表法)

127 delta_days =self._date_diff()128

129 #阳历1901年2月19日为阴历1901年正月初一

130 #阳历1901年1月1日到2月19日共有49天

131 if (delta_days < 49):132 year = self.START_YEAR - 1

133 if (delta_days <19):134 month = 11;135 day = 11 +delta_days136 else:137 month = 12;138 day = delta_days - 18

139 return(year, month, day)140

141 #下面从阴历1901年正月初一算起

142 delta_days -= 49

143 year, month, day = self.START_YEAR, 1, 1

144 #计算年

145 tmp =self._lunar_year_days(year)146 while delta_days >=tmp:147 delta_days -=tmp148 year += 1

149 tmp =self._lunar_year_days(year)150

151 #计算月

152 (foo, tmp) =self._lunar_month_days(year, month)153 while delta_days >=tmp:154 delta_days -=tmp155 if (month ==self._get_leap_month(year)):156 (tmp, foo) =self._lunar_month_days(year, month)157 if (delta_days

161 (foo, tmp) =self._lunar_month_days(year, month)162

163 #计算日

164 day +=delta_days165 return(year, month, day)166

167 def ln_date_str(self):#返回农历日期字符串,形如:农历正月初九

168 _, month, day =self.ln_date()169 return '农历{}月{}'.format(self.lm[month-1], self.ld[(day-1)*2:day*2])170

171 def ln_jie(self): #返回农历节气

172 ct = self.localtime #取当前时间

173 year =ct.year174 for i in range(24):175 #因为两个都是浮点数,不能用相等表示

176 delta = self._julian_day() -self._julian_day_of_ln_jie(year, i)177 if -.5 <= delta <= .5:178 return self.jie[i*2:(i+1)*2]179 return ''

180

181 #显示日历

182 defcalendar(self):183 pass

184

185 #######################################################

186 #下面皆为私有函数

187 #######################################################

188

189 def_date_diff(self):190 '''返回基于1901/01/01日差数'''

191 return (self.localtime - datetime.datetime(1901, 1, 1)).days192

193 def_get_leap_month(self, lunar_year):194 flag = self.g_lunar_month[(lunar_year - self.START_YEAR) // 2]195 if (lunar_year - self.START_YEAR) % 2:196 return flag & 0x0f

197 else:198 return flag >> 4

199

200 def_lunar_month_days(self, lunar_year, lunar_month):201 if (lunar_year

203

204 high, low = 0, 29

205 iBit = 16 -lunar_month;206

207 if (lunar_month > self._get_leap_month(lunar_year) andself._get_leap_month(lunar_year)):208 iBit -= 1

209

210 if (self.g_lunar_month_day[lunar_year - self.START_YEAR] & (1 <

212

213 if (lunar_month ==self._get_leap_month(lunar_year)):214 if (self.g_lunar_month_day[lunar_year - self.START_YEAR] & (1 << (iBit -1))):215 high = 30

216 else:217 high = 29

218

219 return(high, low)220

221 def_lunar_year_days(self, year):222 days =0223 for i in range(1, 13):224 (high, low) =self._lunar_month_days(year, i)225 days +=high226 days +=low227 returndays228

229 #返回指定公历日期的儒略日(http://blog.csdn.net/orbit/article/details/9210413)

230 def_julian_day(self):231 ct = self.localtime #取当前时间

232 year =ct.year233 month =ct.month234 day =ct.day235

236 if month <= 2:237 month += 12

238 year -= 1

239

240 B = year / 100

241 B = 2 - B + year / 400

242

243 dd = day + 0.5000115740 #本日12:00后才是儒略日的开始(过一秒钟)*/

244 return int(365.25 * (year + 4716) + 0.01) + int(30.60001 * (month + 1)) + dd + B - 1524.5

245

246 #返回指定年份的节气的儒略日数(http://blog.csdn.net/orbit/article/details/9210413)

247 def_julian_day_of_ln_jie(self, year, st):248 s_stAccInfo =[249 0.00, 1272494.40, 2548020.60, 3830143.80, 5120226.60, 6420865.80,250 7732018.80, 9055272.60, 10388958.00, 11733065.40, 13084292.40, 14441592.00,251 15800560.80, 17159347.20, 18513766.20, 19862002.20, 21201005.40, 22529659.80,252 23846845.20, 25152606.00, 26447687.40, 27733451.40, 29011921.20, 30285477.60]253

254 #已知1900年小寒时刻为1月6日02:05:00

255 base1900_SlightColdJD = 2415025.5868055555

256

257 if (st < 0) or (st > 24):258 return 0.0

259

260 stJd = 365.24219878 * (year - 1900) + s_stAccInfo[st] / 86400.0

261

262 return base1900_SlightColdJD +stJd263

264

265

266

267 #测试

268 def test(ct=None):269 ln =Lunar(ct)270 print('公历 {} 北京时间 {}'.format(ln.localtime.date(), ln.localtime.time()))271 print('{} 【{}】 {}年 {}日 {}时'.format(ln.ln_date_str(), ln.gz_year(), ln.sx_year(), ln.gz_day(), ln.gz_hour()))272 print('节气:{}'.format(ln.ln_jie()))273

274

275 if __name__ == '__main__':276 ct = datetime.datetime(2015,2,19,13,0,15)277 test(ct)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值