lunar_solar_converter.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. class Lunar:
  2. def __init__(self, lunarYear, lunarMonth, lunarDay, isleap):
  3. self.isleap = isleap
  4. self.lunarDay = lunarDay
  5. self.lunarMonth = lunarMonth
  6. self.lunarYear = lunarYear
  7. class Solar:
  8. def __init__(self, solarYear, solarMonth, solarDay):
  9. self.solarDay = solarDay
  10. self.solarMonth = solarMonth
  11. self.solarYear = solarYear
  12. def GetBitInt(data, length, shift):
  13. return (data & (((1 << length) - 1) << shift)) >> shift
  14. def SolarToInt(y, m, d):
  15. m = (m + 9) % 12
  16. y -= int(m / 10)
  17. return (
  18. 365 * y
  19. + int(y / 4)
  20. - int(y / 100)
  21. + int(y / 400)
  22. + int((m * 306 + 5) / 10)
  23. + (d - 1)
  24. )
  25. def SolarFromInt(g):
  26. y = int((10000 * g + 14780) / 3652425)
  27. ddd = g - (365 * y + int(y / 4) - int(y / 100) + int(y / 400))
  28. if ddd < 0:
  29. y -= 1
  30. ddd = g - (365 * y + int(y / 4) - int(y / 100) + int(y / 400))
  31. mi = int((100 * ddd + 52) / 3060)
  32. mm = (mi + 2) % 12 + 1
  33. y += int((mi + 2) / 12)
  34. dd = ddd - int((mi * 306 + 5) / 10) + 1
  35. solar = Solar(y, mm, dd)
  36. return solar
  37. class LunarSolarConverter:
  38. #####################################################################################
  39. # 1888~2111年农历数据表
  40. # 农历数据 每个元素的存储格式如下:
  41. # 16~13 12 11~0
  42. # 闰几月 闰月日数 1~12月份农历日数(大小月)
  43. # 注:1、bit0表示农历1月份日数,为1表示30天,为0表示29天。bit1表示农历2月份日数,依次类推。
  44. # 2、bit12表示闰月日数,1为30天,0为29天。bit16~bit13表示第几月是闰月(注:为0表示该年无闰月)
  45. # 数据来源参考: http://data.weather.gov.hk/gts/time/conversion1_text_c.htm
  46. #####################################################################################
  47. lunar_month_days = [
  48. 1887,
  49. 0x1694,
  50. 0x16AA,
  51. 0x4AD5,
  52. 0xAB6,
  53. 0xC4B7,
  54. 0x4AE,
  55. 0xA56,
  56. 0xB52A,
  57. 0x1D2A,
  58. 0xD54,
  59. 0x75AA,
  60. 0x156A,
  61. 0x1096D,
  62. 0x95C,
  63. 0x14AE,
  64. 0xAA4D,
  65. 0x1A4C,
  66. 0x1B2A,
  67. 0x8D55,
  68. 0xAD4,
  69. 0x135A,
  70. 0x495D,
  71. 0x95C,
  72. 0xD49B,
  73. 0x149A,
  74. 0x1A4A,
  75. 0xBAA5,
  76. 0x16A8,
  77. 0x1AD4,
  78. 0x52DA,
  79. 0x12B6,
  80. 0xE937,
  81. 0x92E,
  82. 0x1496,
  83. 0xB64B,
  84. 0xD4A,
  85. 0xDA8,
  86. 0x95B5,
  87. 0x56C,
  88. 0x12AE,
  89. 0x492F,
  90. 0x92E,
  91. 0xCC96,
  92. 0x1A94,
  93. 0x1D4A,
  94. 0xADA9,
  95. 0xB5A,
  96. 0x56C,
  97. 0x726E,
  98. 0x125C,
  99. 0xF92D,
  100. 0x192A,
  101. 0x1A94,
  102. 0xDB4A,
  103. 0x16AA,
  104. 0xAD4,
  105. 0x955B,
  106. 0x4BA,
  107. 0x125A,
  108. 0x592B,
  109. 0x152A,
  110. 0xF695,
  111. 0xD94,
  112. 0x16AA,
  113. 0xAAB5,
  114. 0x9B4,
  115. 0x14B6,
  116. 0x6A57,
  117. 0xA56,
  118. 0x1152A,
  119. 0x1D2A,
  120. 0xD54,
  121. 0xD5AA,
  122. 0x156A,
  123. 0x96C,
  124. 0x94AE,
  125. 0x14AE,
  126. 0xA4C,
  127. 0x7D26,
  128. 0x1B2A,
  129. 0xEB55,
  130. 0xAD4,
  131. 0x12DA,
  132. 0xA95D,
  133. 0x95A,
  134. 0x149A,
  135. 0x9A4D,
  136. 0x1A4A,
  137. 0x11AA5,
  138. 0x16A8,
  139. 0x16D4,
  140. 0xD2DA,
  141. 0x12B6,
  142. 0x936,
  143. 0x9497,
  144. 0x1496,
  145. 0x1564B,
  146. 0xD4A,
  147. 0xDA8,
  148. 0xD5B4,
  149. 0x156C,
  150. 0x12AE,
  151. 0xA92F,
  152. 0x92E,
  153. 0xC96,
  154. 0x6D4A,
  155. 0x1D4A,
  156. 0x10D65,
  157. 0xB58,
  158. 0x156C,
  159. 0xB26D,
  160. 0x125C,
  161. 0x192C,
  162. 0x9A95,
  163. 0x1A94,
  164. 0x1B4A,
  165. 0x4B55,
  166. 0xAD4,
  167. 0xF55B,
  168. 0x4BA,
  169. 0x125A,
  170. 0xB92B,
  171. 0x152A,
  172. 0x1694,
  173. 0x96AA,
  174. 0x15AA,
  175. 0x12AB5,
  176. 0x974,
  177. 0x14B6,
  178. 0xCA57,
  179. 0xA56,
  180. 0x1526,
  181. 0x8E95,
  182. 0xD54,
  183. 0x15AA,
  184. 0x49B5,
  185. 0x96C,
  186. 0xD4AE,
  187. 0x149C,
  188. 0x1A4C,
  189. 0xBD26,
  190. 0x1AA6,
  191. 0xB54,
  192. 0x6D6A,
  193. 0x12DA,
  194. 0x1695D,
  195. 0x95A,
  196. 0x149A,
  197. 0xDA4B,
  198. 0x1A4A,
  199. 0x1AA4,
  200. 0xBB54,
  201. 0x16B4,
  202. 0xADA,
  203. 0x495B,
  204. 0x936,
  205. 0xF497,
  206. 0x1496,
  207. 0x154A,
  208. 0xB6A5,
  209. 0xDA4,
  210. 0x15B4,
  211. 0x6AB6,
  212. 0x126E,
  213. 0x1092F,
  214. 0x92E,
  215. 0xC96,
  216. 0xCD4A,
  217. 0x1D4A,
  218. 0xD64,
  219. 0x956C,
  220. 0x155C,
  221. 0x125C,
  222. 0x792E,
  223. 0x192C,
  224. 0xFA95,
  225. 0x1A94,
  226. 0x1B4A,
  227. 0xAB55,
  228. 0xAD4,
  229. 0x14DA,
  230. 0x8A5D,
  231. 0xA5A,
  232. 0x1152B,
  233. 0x152A,
  234. 0x1694,
  235. 0xD6AA,
  236. 0x15AA,
  237. 0xAB4,
  238. 0x94BA,
  239. 0x14B6,
  240. 0xA56,
  241. 0x7527,
  242. 0xD26,
  243. 0xEE53,
  244. 0xD54,
  245. 0x15AA,
  246. 0xA9B5,
  247. 0x96C,
  248. 0x14AE,
  249. 0x8A4E,
  250. 0x1A4C,
  251. 0x11D26,
  252. 0x1AA4,
  253. 0x1B54,
  254. 0xCD6A,
  255. 0xADA,
  256. 0x95C,
  257. 0x949D,
  258. 0x149A,
  259. 0x1A2A,
  260. 0x5B25,
  261. 0x1AA4,
  262. 0xFB52,
  263. 0x16B4,
  264. 0xABA,
  265. 0xA95B,
  266. 0x936,
  267. 0x1496,
  268. 0x9A4B,
  269. 0x154A,
  270. 0x136A5,
  271. 0xDA4,
  272. 0x15AC,
  273. ]
  274. # 额外添加数据,方便快速计算阴历转阳历 每个元素的存储格式如下:
  275. # 12~7 6~5 4~0
  276. # 离元旦多少天 春节月 春节日
  277. #####################################################################################
  278. solar_1_1 = [
  279. 1887,
  280. 0xEC04C,
  281. 0xEC23F,
  282. 0xEC435,
  283. 0xEC649,
  284. 0xEC83E,
  285. 0xECA51,
  286. 0xECC46,
  287. 0xECE3A,
  288. 0xED04D,
  289. 0xED242,
  290. 0xED436,
  291. 0xED64A,
  292. 0xED83F,
  293. 0xEDA53,
  294. 0xEDC48,
  295. 0xEDE3D,
  296. 0xEE050,
  297. 0xEE244,
  298. 0xEE439,
  299. 0xEE64D,
  300. 0xEE842,
  301. 0xEEA36,
  302. 0xEEC4A,
  303. 0xEEE3E,
  304. 0xEF052,
  305. 0xEF246,
  306. 0xEF43A,
  307. 0xEF64E,
  308. 0xEF843,
  309. 0xEFA37,
  310. 0xEFC4B,
  311. 0xEFE41,
  312. 0xF0054,
  313. 0xF0248,
  314. 0xF043C,
  315. 0xF0650,
  316. 0xF0845,
  317. 0xF0A38,
  318. 0xF0C4D,
  319. 0xF0E42,
  320. 0xF1037,
  321. 0xF124A,
  322. 0xF143E,
  323. 0xF1651,
  324. 0xF1846,
  325. 0xF1A3A,
  326. 0xF1C4E,
  327. 0xF1E44,
  328. 0xF2038,
  329. 0xF224B,
  330. 0xF243F,
  331. 0xF2653,
  332. 0xF2848,
  333. 0xF2A3B,
  334. 0xF2C4F,
  335. 0xF2E45,
  336. 0xF3039,
  337. 0xF324D,
  338. 0xF3442,
  339. 0xF3636,
  340. 0xF384A,
  341. 0xF3A3D,
  342. 0xF3C51,
  343. 0xF3E46,
  344. 0xF403B,
  345. 0xF424E,
  346. 0xF4443,
  347. 0xF4638,
  348. 0xF484C,
  349. 0xF4A3F,
  350. 0xF4C52,
  351. 0xF4E48,
  352. 0xF503C,
  353. 0xF524F,
  354. 0xF5445,
  355. 0xF5639,
  356. 0xF584D,
  357. 0xF5A42,
  358. 0xF5C35,
  359. 0xF5E49,
  360. 0xF603E,
  361. 0xF6251,
  362. 0xF6446,
  363. 0xF663B,
  364. 0xF684F,
  365. 0xF6A43,
  366. 0xF6C37,
  367. 0xF6E4B,
  368. 0xF703F,
  369. 0xF7252,
  370. 0xF7447,
  371. 0xF763C,
  372. 0xF7850,
  373. 0xF7A45,
  374. 0xF7C39,
  375. 0xF7E4D,
  376. 0xF8042,
  377. 0xF8254,
  378. 0xF8449,
  379. 0xF863D,
  380. 0xF8851,
  381. 0xF8A46,
  382. 0xF8C3B,
  383. 0xF8E4F,
  384. 0xF9044,
  385. 0xF9237,
  386. 0xF944A,
  387. 0xF963F,
  388. 0xF9853,
  389. 0xF9A47,
  390. 0xF9C3C,
  391. 0xF9E50,
  392. 0xFA045,
  393. 0xFA238,
  394. 0xFA44C,
  395. 0xFA641,
  396. 0xFA836,
  397. 0xFAA49,
  398. 0xFAC3D,
  399. 0xFAE52,
  400. 0xFB047,
  401. 0xFB23A,
  402. 0xFB44E,
  403. 0xFB643,
  404. 0xFB837,
  405. 0xFBA4A,
  406. 0xFBC3F,
  407. 0xFBE53,
  408. 0xFC048,
  409. 0xFC23C,
  410. 0xFC450,
  411. 0xFC645,
  412. 0xFC839,
  413. 0xFCA4C,
  414. 0xFCC41,
  415. 0xFCE36,
  416. 0xFD04A,
  417. 0xFD23D,
  418. 0xFD451,
  419. 0xFD646,
  420. 0xFD83A,
  421. 0xFDA4D,
  422. 0xFDC43,
  423. 0xFDE37,
  424. 0xFE04B,
  425. 0xFE23F,
  426. 0xFE453,
  427. 0xFE648,
  428. 0xFE83C,
  429. 0xFEA4F,
  430. 0xFEC44,
  431. 0xFEE38,
  432. 0xFF04C,
  433. 0xFF241,
  434. 0xFF436,
  435. 0xFF64A,
  436. 0xFF83E,
  437. 0xFFA51,
  438. 0xFFC46,
  439. 0xFFE3A,
  440. 0x10004E,
  441. 0x100242,
  442. 0x100437,
  443. 0x10064B,
  444. 0x100841,
  445. 0x100A53,
  446. 0x100C48,
  447. 0x100E3C,
  448. 0x10104F,
  449. 0x101244,
  450. 0x101438,
  451. 0x10164C,
  452. 0x101842,
  453. 0x101A35,
  454. 0x101C49,
  455. 0x101E3D,
  456. 0x102051,
  457. 0x102245,
  458. 0x10243A,
  459. 0x10264E,
  460. 0x102843,
  461. 0x102A37,
  462. 0x102C4B,
  463. 0x102E3F,
  464. 0x103053,
  465. 0x103247,
  466. 0x10343B,
  467. 0x10364F,
  468. 0x103845,
  469. 0x103A38,
  470. 0x103C4C,
  471. 0x103E42,
  472. 0x104036,
  473. 0x104249,
  474. 0x10443D,
  475. 0x104651,
  476. 0x104846,
  477. 0x104A3A,
  478. 0x104C4E,
  479. 0x104E43,
  480. 0x105038,
  481. 0x10524A,
  482. 0x10543E,
  483. 0x105652,
  484. 0x105847,
  485. 0x105A3B,
  486. 0x105C4F,
  487. 0x105E45,
  488. 0x106039,
  489. 0x10624C,
  490. 0x106441,
  491. 0x106635,
  492. 0x106849,
  493. 0x106A3D,
  494. 0x106C51,
  495. 0x106E47,
  496. 0x10703C,
  497. 0x10724F,
  498. 0x107444,
  499. 0x107638,
  500. 0x10784C,
  501. 0x107A3F,
  502. 0x107C53,
  503. 0x107E48,
  504. ]
  505. def LunarToSolar(self, lunar):
  506. days = LunarSolarConverter.lunar_month_days[
  507. lunar.lunarYear - LunarSolarConverter.lunar_month_days[0]
  508. ]
  509. leap = GetBitInt(days, 4, 13)
  510. offset = 0
  511. loopend = leap
  512. if not lunar.isleap:
  513. if lunar.lunarMonth <= leap or leap == 0:
  514. loopend = lunar.lunarMonth - 1
  515. else:
  516. loopend = lunar.lunarMonth
  517. for i in range(0, loopend):
  518. offset += GetBitInt(days, 1, 12 - i) == 1 and 30 or 29
  519. offset += lunar.lunarDay
  520. solar11 = LunarSolarConverter.solar_1_1[
  521. lunar.lunarYear - LunarSolarConverter.solar_1_1[0]
  522. ]
  523. y = GetBitInt(solar11, 12, 9)
  524. m = GetBitInt(solar11, 4, 5)
  525. d = GetBitInt(solar11, 5, 0)
  526. return SolarFromInt(SolarToInt(y, m, d) + offset - 1)
  527. def SolarToLunar(self, solar):
  528. lunar = Lunar(0, 0, 0, False)
  529. index = solar.solarYear - LunarSolarConverter.solar_1_1[0]
  530. data = (solar.solarYear << 9) | (solar.solarMonth << 5) | solar.solarDay
  531. if LunarSolarConverter.solar_1_1[index] > data:
  532. index -= 1
  533. solar11 = LunarSolarConverter.solar_1_1[index]
  534. y = GetBitInt(solar11, 12, 9)
  535. m = GetBitInt(solar11, 4, 5)
  536. d = GetBitInt(solar11, 5, 0)
  537. offset = SolarToInt(
  538. solar.solarYear, solar.solarMonth, solar.solarDay
  539. ) - SolarToInt(y, m, d)
  540. days = LunarSolarConverter.lunar_month_days[index]
  541. leap = GetBitInt(days, 4, 13)
  542. lunarY = index + LunarSolarConverter.solar_1_1[0]
  543. lunarM = 1
  544. offset += 1
  545. for i in range(0, 13):
  546. dm = GetBitInt(days, 1, 12 - i) == 1 and 30 or 29
  547. if offset > dm:
  548. lunarM += 1
  549. offset -= dm
  550. else:
  551. break
  552. lunarD = int(offset)
  553. lunar.lunarYear = lunarY
  554. lunar.lunarMonth = lunarM
  555. lunar.isleap = False
  556. if leap != 0 and lunarM > leap:
  557. lunar.lunarMonth = lunarM - 1
  558. if lunarM == leap + 1:
  559. lunar.isleap = True
  560. lunar.lunarDay = lunarD
  561. return lunar
  562. def __init__(self):
  563. pass