大杂烩。作为自己的记录,保存。

两个要点

1、公历转农历用了查表法(第126行)

2、节气用了天文法?(第176行)

 运行图 (背景是hao123万年历)

源代码

  1. # lunar.py
  2. # 2015/02/27 罗兵
  3. import datetime
  4.  
  5. class Lunar(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, #
  13. 0xa4d8, 0xa4d0, 0xd250, 0xd548, 0xb550, 0x56a0, 0x96d0, 0x95b0, 0x49b8, 0x49b0, #
  14. 0xa4b0, 0xb258, 0x6a50, 0x6d40, 0xada8, 0x2b60, 0x9570, 0x4978, 0x4970, 0x64b0, #
  15. 0xd4a0, 0xea50, 0x6d48, 0x5ad0, 0x2b60, 0x9370, 0x92e0, 0xc968, 0xc950, 0xd4a0, #
  16. 0xda50, 0xb550, 0x56a0, 0xaad8, 0x25d0, 0x92d0, 0xc958, 0xa950, 0xb4a8, 0x6ca0, #
  17. 0xb550, 0x55a8, 0x4da0, 0xa5b0, 0x52b8, 0x52b0, 0xa950, 0xe950, 0x6aa0, 0xad50, #
  18. 0xab50, 0x4b60, 0xa570, 0xa570, 0x5260, 0xe930, 0xd950, 0x5aa8, 0x56a0, 0x96d0, #
  19. 0x4ae8, 0x4ad0, 0xa4d0, 0xd268, 0xd250, 0xd528, 0xb540, 0xb6a0, 0x96d0, 0x95b0, #
  20. 0x49b0, 0xa4b8, 0xa4b0, 0xb258, 0x6a50, 0x6d40, 0xada0, 0xab60, 0x9370, 0x4978, #
  21. 0x4970, 0x64b0, 0x6a50, 0xea50, 0x6b28, 0x5ac0, 0xab60, 0x9368, 0x92e0, 0xc960, #
  22. 0xd4a8, 0xd4a0, 0xda50, 0x5aa8, 0x56a0, 0xaad8, 0x25d0, 0x92d0, 0xc958, 0xa950, #
  23. 0xb4a0, 0xb550, 0xb550, 0x55a8, 0x4ba0, 0xa5b0, 0x52b8, 0x52b0, 0xa930, 0x74a8, #
  24. 0x6aa0, 0xad50, 0x4da8, 0x4b60, 0x9570, 0xa4e0, 0xd260, 0xe930, 0xd530, 0x5aa0, #
  25. 0x6b50, 0x96d0, 0x4ae8, 0x4ad0, 0xa4d0, 0xd258, 0xd250, 0xd520, 0xdaa0, 0xb5a0, #
  26. 0x56d0, 0x4ad8, 0x49b0, 0xa4b8, 0xa4b0, 0xaa50, 0xb528, 0x6d20, 0xada0, 0x55b0, #
  27. ]
  28.  
  29. #数组gLanarMonth存放阴历1901年到2050年闰月的月份,如没有则为0,每字节存两年
  30. g_lunar_month = [
  31. 0x00, 0x50, 0x04, 0x00, 0x20, #
  32. 0x60, 0x05, 0x00, 0x20, 0x70, #
  33. 0x05, 0x00, 0x40, 0x02, 0x06, #
  34. 0x00, 0x50, 0x03, 0x07, 0x00, #
  35. 0x60, 0x04, 0x00, 0x20, 0x70, #
  36. 0x05, 0x00, 0x30, 0x80, 0x06, #
  37. 0x00, 0x40, 0x03, 0x07, 0x00, #
  38. 0x50, 0x04, 0x08, 0x00, 0x60, #
  39. 0x04, 0x0a, 0x00, 0x60, 0x05, #
  40. 0x00, 0x30, 0x80, 0x05, 0x00, #
  41. 0x40, 0x02, 0x07, 0x00, 0x50, #
  42. 0x04, 0x09, 0x00, 0x60, 0x04, #
  43. 0x00, 0x20, 0x60, 0x05, 0x00, #
  44. 0x30, 0xb0, 0x06, 0x00, 0x50, #
  45. 0x02, 0x07, 0x00, 0x50, 0x03 #
  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 else datetime.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. return self.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 else y
  89. M = ct.month #取月份(若为1月、2月则分别按13、14来计算)
  90. M = M + 12 if ct.month == 1 or ct.month == 2 else M
  91. 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. return self.zhi[Z]
  113.  
  114. def ln_year(self): # 返回农历年
  115. year, _, _ = self.ln_date()
  116. return year
  117.  
  118. def ln_month(self): # 返回农历月
  119. _, month, _ = self.ln_date()
  120. return month
  121.  
  122. def ln_day(self): # 返回农历日
  123. _, _, day = self.ln_date()
  124. return day
  125.  
  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_days
  136. 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 -= tmp
  148. 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 -= tmp
  155. if (month == self._get_leap_month(year)):
  156. (tmp, foo) = self._lunar_month_days(year, month)
  157. if (delta_days < tmp):
  158. return (0, 0, 0)
  159. delta_days -= tmp
  160. month += 1
  161. (foo, tmp) = self._lunar_month_days(year, month)
  162.  
  163. #计算日
  164. day += delta_days
  165. 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.year
  174. 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. def calendar(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)).days
  192.  
  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 < self.START_YEAR):
  202. return 30
  203.  
  204. high, low = 0, 29
  205. iBit = 16 - lunar_month;
  206.  
  207. if (lunar_month > self._get_leap_month(lunar_year) and self._get_leap_month(lunar_year)):
  208. iBit -= 1
  209.  
  210. if (self.g_lunar_month_day[lunar_year - self.START_YEAR] & (1 << iBit)):
  211. low += 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 = 0
  223. for i in range(1, 13):
  224. (high, low) = self._lunar_month_days(year, i)
  225. days += high
  226. days += low
  227. return days
  228.  
  229. # 返回指定公历日期的儒略日(http://blog.csdn.net/orbit/article/details/9210413)
  230. def _julian_day(self):
  231. ct = self.localtime #取当前时间
  232. year = ct.year
  233. month = ct.month
  234. day = ct.day
  235.  
  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 + stJd
  263.  
  264. # 测试
  265. def test(ct=None):
  266. ln = Lunar(ct)
  267. print('公历 {} 北京时间 {}'.format(ln.localtime.date(), ln.localtime.time()))
  268. print('{} 【{}】 {}年 {}日 {}时'.format(ln.ln_date_str(), ln.gz_year(), ln.sx_year(), ln.gz_day(), ln.gz_hour()))
  269. print('节气:{}'.format(ln.ln_jie()))
  270.  
  271. if __name__ == '__main__':
  272. ct = datetime.datetime(2015,2,19,13,0,15)
  273. test(ct)

公历转农历的python实现的更多相关文章

  1. C#公历转农历算法

    C#公历转农历算法,高手们也可以改写一下让其更加有效率! Code/// <summary> /// LunDay 的摘要说明. /// 用法说明 /// 直接调用即可,比较简单 /// ...

  2. iOS 获取公历、农历日期的年月日

    iOS 获取公历.农历日期的年月日 介绍三种方法获取 Date (NSDate) 的年月日. 用 date 表示当前日期.测试日期为公历 2017 年 2 月 5 日,农历丁酉年,鸡年,正月初九. l ...

  3. Java 公历转农历,然后农历减一年(或者几天或者任意天),再把这个日期转成公历

    由于系统的提醒有可能是农历的今天或指定时间要用quartz 实现定时任务 公历转农历,然后农历减一年(或者几天或者任意天),再把这个日期转成公历. 网上很多农历转公历的程序都有问题,QQ.百度的也有 ...

  4. Andorid 之日历控件,可左右滑动,包含公历,农历,节假日等

    公司项目需要日历这个功能,经过查阅资料写了个demo,包含公历,农历,节假日等,还可左右滑动. 效果图: 代码: public class MainActivity extends AppCompat ...

  5. javascript 公历与农历相互转换工具类

    /** * 公历[1900-1-31,2100-12-31]时间区间内的公历.农历互转 * @charset UTF-8 * @Author Jea杨(JJonline@JJonline.Cn) * ...

  6. python3实现万年历(包括公历、农历、节气、节日)

    #!/usr/local/bin/python3 # coding=utf-8 # Created: 20/07/2012 # Copyright: http://www.cnblogs.com/tx ...

  7. C# 公历转农历

    /// <summary>     /// LunDay 的摘要说明.     /// 用法说明     /// 直接调用即可,比较简单     /// </summary> ...

  8. 公历和农历转换JS代码

    <!-- function CalConv(M) { FIRSTYEAR = 1936; LASTYEAR = 2031; LunarCal = [ new tagLunarCal(23, 3, ...

  9. JS:公历、农历互转

    先申明这段代码不是我写的,纯粹只是觉的比较好用,所以记录下来以后继续使用,也同样分享给大家,大家有更好的可以推荐给我,谢谢! function CalConv(M, dateStr) { if (da ...

随机推荐

  1. Spring常用注解简单汇总

    使用注解之前要开启自动扫描功能,其中base-package为需要扫描的包(含子包). <context:component-scan base-package="cn.test&qu ...

  2. 不同服务器数据库之间的数据定时同步到sql server (支持mysql,oracle数据库同步到sql server)

    1,在目标数据库新增服务器对象->连接到服务器->新建服务器连接 2,编写数据同步业务PROC ALTER PROC TestProc AS BEGIN --打开完全事物回滚 SET XA ...

  3. UIWindow的windowLevel详解

    UIWindow的windowLevel详解

  4. Linux学习---Linux用户审计简单版

    [root@localhost root]# vim /etc/profile # SHENJI history USER=`whoami` USER_IP=`who -u am i 2>/de ...

  5. DoraHacks的笔记

    DoraHacks的笔记

  6. centos 增加网卡

    CentOS 6添加网卡的方法 (2013-11-26 17:19:44) 转载▼ 标签: it 分类: Linux 前段时间安装了1台XEN server虚拟机,之前只用了1个网卡,ip是10.11 ...

  7. html操作

    HTML(hyper text markup language): 超文本标记语言,标准通用标记语言下的一个应用. 超文本就是指页面内可以包含图片.连接.音乐.程序等非文字元素. 超文本标记语言的结构 ...

  8. 多线程操作C++ STL vector出现概率coredump问题及尽量避免锁的双缓冲队列

    多线程操作全局变量,必须考虑同步问题,否则可能出现数据不一致, 甚至触发coredump. 前段时间, 遇到一个多线程操作了全局的vector的问题,  程序崩了.场景是这样的:某全局配置参数保存在一 ...

  9. 算法题:整形数组找a和b使得a+b=n

    题目: 数组 A 由 1000 万个随机正整数 (int) 组成,设计算法,给定整数 n,在 A 中找出 a 和 b,使其符合如下等式: n = a + b 解题思路: 1. 1000w个随机正整数占 ...

  10. HAproxy.md

    HAProxy HAProxy是什么 HAProxy(High Available Proxy)是基于四层和七层的高可用负载均衡代理服务器,配置简单.支持多达上万条并发请求. HAProxy工作原理 ...