Python實(shí)現(xiàn)公歷(陽歷)轉(zhuǎn)農(nóng)歷(陰歷)的方法示例
本文實(shí)例講述了Python實(shí)現(xiàn)公歷(陽歷)轉(zhuǎn)農(nóng)歷(陰歷)的方法。分享給大家供大家參考,具體如下:
兩個(gè)要點(diǎn):
1、公歷轉(zhuǎn)農(nóng)歷用了查表法(第126行)
2、節(jié)氣用了天文法?(第176行)
運(yùn)行圖 (背景是hao123萬年歷)
源代碼:
# lunar.py # 2015/02/27 羅兵 import datetime class Lunar(object): #****************************************************************************** # 下面為陰歷計(jì)算所需的數(shù)據(jù),為節(jié)省存儲(chǔ)空間,所以采用下面比較變態(tài)的存儲(chǔ)方法. #****************************************************************************** #數(shù)組g_lunar_month_day存入陰歷1901年到2050年每年中的月天數(shù)信息, #陰歷每月只能是29或30天,一年用12(或13)個(gè)二進(jìn)制位表示,對應(yīng)位為1表30天,否則為29天 g_lunar_month_day = [ 0x4ae0, 0xa570, 0x5268, 0xd260, 0xd950, 0x6aa8, 0x56a0, 0x9ad0, 0x4ae8, 0x4ae0, #1910 0xa4d8, 0xa4d0, 0xd250, 0xd548, 0xb550, 0x56a0, 0x96d0, 0x95b0, 0x49b8, 0x49b0, #1920 0xa4b0, 0xb258, 0x6a50, 0x6d40, 0xada8, 0x2b60, 0x9570, 0x4978, 0x4970, 0x64b0, #1930 0xd4a0, 0xea50, 0x6d48, 0x5ad0, 0x2b60, 0x9370, 0x92e0, 0xc968, 0xc950, 0xd4a0, #1940 0xda50, 0xb550, 0x56a0, 0xaad8, 0x25d0, 0x92d0, 0xc958, 0xa950, 0xb4a8, 0x6ca0, #1950 0xb550, 0x55a8, 0x4da0, 0xa5b0, 0x52b8, 0x52b0, 0xa950, 0xe950, 0x6aa0, 0xad50, #1960 0xab50, 0x4b60, 0xa570, 0xa570, 0x5260, 0xe930, 0xd950, 0x5aa8, 0x56a0, 0x96d0, #1970 0x4ae8, 0x4ad0, 0xa4d0, 0xd268, 0xd250, 0xd528, 0xb540, 0xb6a0, 0x96d0, 0x95b0, #1980 0x49b0, 0xa4b8, 0xa4b0, 0xb258, 0x6a50, 0x6d40, 0xada0, 0xab60, 0x9370, 0x4978, #1990 0x4970, 0x64b0, 0x6a50, 0xea50, 0x6b28, 0x5ac0, 0xab60, 0x9368, 0x92e0, 0xc960, #2000 0xd4a8, 0xd4a0, 0xda50, 0x5aa8, 0x56a0, 0xaad8, 0x25d0, 0x92d0, 0xc958, 0xa950, #2010 0xb4a0, 0xb550, 0xb550, 0x55a8, 0x4ba0, 0xa5b0, 0x52b8, 0x52b0, 0xa930, 0x74a8, #2020 0x6aa0, 0xad50, 0x4da8, 0x4b60, 0x9570, 0xa4e0, 0xd260, 0xe930, 0xd530, 0x5aa0, #2030 0x6b50, 0x96d0, 0x4ae8, 0x4ad0, 0xa4d0, 0xd258, 0xd250, 0xd520, 0xdaa0, 0xb5a0, #2040 0x56d0, 0x4ad8, 0x49b0, 0xa4b8, 0xa4b0, 0xaa50, 0xb528, 0x6d20, 0xada0, 0x55b0, #2050 ] #數(shù)組gLanarMonth存放陰歷1901年到2050年閏月的月份,如沒有則為0,每字節(jié)存兩年 g_lunar_month = [ 0x00, 0x50, 0x04, 0x00, 0x20, #1910 0x60, 0x05, 0x00, 0x20, 0x70, #1920 0x05, 0x00, 0x40, 0x02, 0x06, #1930 0x00, 0x50, 0x03, 0x07, 0x00, #1940 0x60, 0x04, 0x00, 0x20, 0x70, #1950 0x05, 0x00, 0x30, 0x80, 0x06, #1960 0x00, 0x40, 0x03, 0x07, 0x00, #1970 0x50, 0x04, 0x08, 0x00, 0x60, #1980 0x04, 0x0a, 0x00, 0x60, 0x05, #1990 0x00, 0x30, 0x80, 0x05, 0x00, #2000 0x40, 0x02, 0x07, 0x00, 0x50, #2010 0x04, 0x09, 0x00, 0x60, 0x04, #2020 0x00, 0x20, 0x60, 0x05, 0x00, #2030 0x30, 0xb0, 0x06, 0x00, 0x50, #2040 0x02, 0x07, 0x00, 0x50, 0x03 #2050 ] START_YEAR = 1901 # 天干 gan = '甲乙丙丁戊己庚辛壬癸' # 地支 zhi = '子丑寅卯辰巳午未申酉戌亥' # 生肖 xiao = '鼠?;⑼谬埳唏R羊猴雞狗豬' # 月份 lm = '正二三四五六七八九十冬臘' # 日份 ld = '初一初二初三初四初五初六初七初八初九初十十一十二十三十四十五十六十七十八十九二十廿一廿二廿三廿四廿五廿六廿七廿八廿九三十' # 節(jié)氣 jie = '小寒大寒立春雨水驚蟄春分清明谷雨立夏小滿芒種夏至小暑大暑立秋處暑白露秋分寒露霜降立冬小雪大雪冬至' def __init__(self, dt = None): '''初始化:參數(shù)為datetime.datetime類實(shí)例,默認(rèn)當(dāng)前時(shí)間''' self.localtime = dt if dt else datetime.datetime.today() def sx_year(self): # 返回生肖年 ct = self.localtime #取當(dāng)前時(shí)間 year = self.ln_year() - 3 - 1 # 農(nóng)歷年份減3 (說明:補(bǔ)減1) year = year % 12 # 模12,得到地支數(shù) return self.xiao[year] def gz_year(self): # 返回干支紀(jì)年 ct = self.localtime #取當(dāng)前時(shí)間 year = self.ln_year() - 3 - 1 # 農(nóng)歷年份減3 (說明:補(bǔ)減1) G = year % 10 # 模10,得到天干數(shù) Z = year % 12 # 模12,得到地支數(shù) return self.gan[G] + self.zhi[Z] def gz_month(self): # 返回干支紀(jì)月(未實(shí)現(xiàn)) pass def gz_day(self): # 返回干支紀(jì)日 ct = self.localtime #取當(dāng)前時(shí)間 C = ct.year // 100 #取世紀(jì)數(shù),減一 y = ct.year % 100 #取年份后兩位(若為1月、2月則當(dāng)前年份減一) y = y - 1 if ct.month == 1 or ct.month == 2 else y M = ct.month #取月份(若為1月、2月則分別按13、14來計(jì)算) M = M + 12 if ct.month == 1 or ct.month == 2 else M d = ct.day #取日數(shù) i = 0 if ct.month % 2 == 1 else 6 #取i (奇數(shù)月i=0,偶數(shù)月i=6) #下面兩個(gè)是網(wǎng)上的公式 # http://baike.baidu.com/link?url=MbTKmhrTHTOAz735gi37tEtwd29zqE9GJ92cZQZd0X8uFO5XgmyMKQru6aetzcGadqekzKd3nZHVS99rewya6q # 計(jì)算干(說明:補(bǔ)減1) G = 4 * C + C // 4 + 5 * y + y // 4 + 3 * (M + 1) // 5 + d - 3 - 1 G = G % 10 # 計(jì)算支(說明:補(bǔ)減1) Z = 8 * C + C // 4 + 5 * y + y // 4 + 3 * (M + 1) // 5 + d + 7 + i - 1 Z = Z % 12 #返回 干支紀(jì)日 return self.gan[G] + self.zhi[Z] def gz_hour(self): # 返回干支紀(jì)時(shí)(時(shí)辰) ct = self.localtime #取當(dāng)前時(shí)間 #計(jì)算支 Z = round((ct.hour/2) + 0.1) % 12 # 之所以加0.1是因?yàn)閞ound的bug!! #返回 干支紀(jì)時(shí)(時(shí)辰) return self.zhi[Z] def ln_year(self): # 返回農(nóng)歷年 year, _, _ = self.ln_date() return year def ln_month(self): # 返回農(nóng)歷月 _, month, _ = self.ln_date() return month def ln_day(self): # 返回農(nóng)歷日 _, _, day = self.ln_date() return day def ln_date(self): # 返回農(nóng)歷日期整數(shù)元組(年、月、日)(查表法) delta_days = self._date_diff() #陽歷1901年2月19日為陰歷1901年正月初一 #陽歷1901年1月1日到2月19日共有49天 if (delta_days < 49): year = self.START_YEAR - 1 if (delta_days <19): month = 11; day = 11 + delta_days else: month = 12; day = delta_days - 18 return (year, month, day) #下面從陰歷1901年正月初一算起 delta_days -= 49 year, month, day = self.START_YEAR, 1, 1 #計(jì)算年 tmp = self._lunar_year_days(year) while delta_days >= tmp: delta_days -= tmp year += 1 tmp = self._lunar_year_days(year) #計(jì)算月 (foo, tmp) = self._lunar_month_days(year, month) while delta_days >= tmp: delta_days -= tmp if (month == self._get_leap_month(year)): (tmp, foo) = self._lunar_month_days(year, month) if (delta_days < tmp): return (0, 0, 0) return (year, month, delta_days+1) delta_days -= tmp month += 1 (foo, tmp) = self._lunar_month_days(year, month) #計(jì)算日 day += delta_days return (year, month, day) def ln_date_str(self):# 返回農(nóng)歷日期字符串,形如:農(nóng)歷正月初九 _, month, day = self.ln_date() return '農(nóng)歷{}月{}'.format(self.lm[month-1], self.ld[(day-1)*2:day*2]) def ln_jie(self): # 返回農(nóng)歷節(jié)氣 ct = self.localtime #取當(dāng)前時(shí)間 year = ct.year for i in range(24): #因?yàn)閮蓚€(gè)都是浮點(diǎn)數(shù),不能用相等表示 delta = self._julian_day() - self._julian_day_of_ln_jie(year, i) if -.5 <= delta <= .5: return self.jie[i*2:(i+1)*2] return '' #顯示日歷 def calendar(self): pass ####################################################### # 下面皆為私有函數(shù) ####################################################### def _date_diff(self): '''返回基于1901/01/01日差數(shù)''' return (self.localtime - datetime.datetime(1901, 1, 1)).days def _get_leap_month(self, lunar_year): flag = self.g_lunar_month[(lunar_year - self.START_YEAR) // 2] if (lunar_year - self.START_YEAR) % 2: return flag & 0x0f else: return flag >> 4 def _lunar_month_days(self, lunar_year, lunar_month): if (lunar_year < self.START_YEAR): return 30 high, low = 0, 29 iBit = 16 - lunar_month; if (lunar_month > self._get_leap_month(lunar_year) and self._get_leap_month(lunar_year)): iBit -= 1 if (self.g_lunar_month_day[lunar_year - self.START_YEAR] & (1 << iBit)): low += 1 if (lunar_month == self._get_leap_month(lunar_year)): if (self.g_lunar_month_day[lunar_year - self.START_YEAR] & (1 << (iBit -1))): high = 30 else: high = 29 return (high, low) def _lunar_year_days(self, year): days = 0 for i in range(1, 13): (high, low) = self._lunar_month_days(year, i) days += high days += low return days # 返回指定公歷日期的儒略日 def _julian_day(self): ct = self.localtime #取當(dāng)前時(shí)間 year = ct.year month = ct.month day = ct.day if month <= 2: month += 12 year -= 1 B = year / 100 B = 2 - B + year / 400 dd = day + 0.5000115740 #本日12:00后才是儒略日的開始(過一秒鐘)*/ return int(365.25 * (year + 4716) + 0.01) + int(30.60001 * (month + 1)) + dd + B - 1524.5 # 返回指定年份的節(jié)氣的儒略日數(shù) def _julian_day_of_ln_jie(self, year, st): s_stAccInfo =[ 0.00, 1272494.40, 2548020.60, 3830143.80, 5120226.60, 6420865.80, 7732018.80, 9055272.60, 10388958.00, 11733065.40, 13084292.40, 14441592.00, 15800560.80, 17159347.20, 18513766.20, 19862002.20, 21201005.40, 22529659.80, 23846845.20, 25152606.00, 26447687.40, 27733451.40, 29011921.20, 30285477.60] #已知1900年小寒時(shí)刻為1月6日02:05:00 base1900_SlightColdJD = 2415025.5868055555 if (st < 0) or (st > 24): return 0.0 stJd = 365.24219878 * (year - 1900) + s_stAccInfo[st] / 86400.0 return base1900_SlightColdJD + stJd # 測試 def test(ct=None): ln = Lunar(ct) print('公歷 {} 北京時(shí)間 {}'.format(ln.localtime.date(), ln.localtime.time())) print('{} 【{}】 {}年 {}日 {}時(shí)'.format(ln.ln_date_str(), ln.gz_year(), ln.sx_year(), ln.gz_day(), ln.gz_hour())) print('節(jié)氣:{}'.format(ln.ln_jie())) if __name__ == '__main__': ct = datetime.datetime(2015,2,19,13,0,15) test(ct)
PS:這里再為大家推薦幾款日歷相關(guān)在線工具供大家參考:
在線陰歷/陽歷轉(zhuǎn)換工具:
http://tools.jb51.net/bianmin/yinli2yangli
網(wǎng)頁萬年歷日歷:
http://tools.jb51.net/bianmin/webwannianli
在線萬年歷日歷:
http://tools.jb51.net/bianmin/wannianli
在線萬年歷黃歷flash版:
http://tools.jb51.net/bianmin/flashwnl
另外,本站歷史上的今天也有相似的農(nóng)歷日期顯示功能:
http://tools.jb51.net/bianmin/lishi
更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python日期與時(shí)間操作技巧總結(jié)》、《Python數(shù)學(xué)運(yùn)算技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門與進(jìn)階經(jīng)典教程》
希望本文所述對大家Python程序設(shè)計(jì)有所幫助。
- python實(shí)現(xiàn)的陽歷轉(zhuǎn)陰歷(農(nóng)歷)算法
- Python日期的加減等操作的示例
- 利用python獲取當(dāng)前日期前后N天或N月日期的方法示例
- python 計(jì)算兩個(gè)日期相差多少個(gè)月實(shí)例代碼
- Python計(jì)算兩個(gè)日期相差天數(shù)的方法示例
- python編程開發(fā)之日期操作實(shí)例分析
- python根據(jù)日期返回星期幾的方法
- python實(shí)現(xiàn)字符串和日期相互轉(zhuǎn)換的方法
- python操作日期和時(shí)間的方法
- Python實(shí)用日期時(shí)間處理方法匯總
相關(guān)文章
python連接、操作mongodb數(shù)據(jù)庫的方法實(shí)例詳解
這篇文章主要介紹了python連接、操作mongodb數(shù)據(jù)庫的方法,結(jié)合實(shí)例形式詳細(xì)分析了Python針對MongoDB數(shù)據(jù)庫的連接、查詢、排序等相關(guān)操作技巧,需要的朋友可以參考下2019-09-09淺談Keras參數(shù) input_shape、input_dim和input_length用法
這篇文章主要介紹了淺談Keras參數(shù) input_shape、input_dim和input_length用法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06django定期執(zhí)行任務(wù)(實(shí)例講解)
下面小編就為大家?guī)硪黄猟jango定期執(zhí)行任務(wù)(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11Pandas使用分隔符或正則表達(dá)式將字符串拆分為多列
本文主要介紹了Pandas使用分隔符或正則表達(dá)式將字符串拆分為多列,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02Python實(shí)現(xiàn)標(biāo)記數(shù)組的連通域
這篇文章主要為大家詳細(xì)介紹了如何通過Python實(shí)現(xiàn)標(biāo)記數(shù)組的連通域,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Python有一定的幫助,需要的可以參考一下2023-04-04Python如何用NumPy讀取和保存點(diǎn)云數(shù)據(jù)
這篇文章主要介紹了Python如何用NumPy讀取和保存點(diǎn)云數(shù)據(jù),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08Python簡單調(diào)用MySQL存儲(chǔ)過程并獲得返回值的方法
這篇文章主要介紹了Python調(diào)用MySQL存儲(chǔ)過程并獲得返回值的方法,涉及Python操作MySQL存儲(chǔ)過程的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07