打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
VBA农历转公历
userphoto

2023.10.13 河南

关注
  • 基础知识:

    农历是阴阳合历,每年有12个月,大月30天,小月29天,如果有闰月,闰月也分大小月,也是30天或29天。一年有24节气,节气以太阳运转轨迹为准,基本原则是每月两个节气,分别在月首3号左右,月尾24号左右。闰月通常设置在只有一个节气的月份之后。农历新年,是以24节气的立春为界,立春后开始新的一年。

  • 编程设计:

    编程源代码原型:http://s.o4u.com/host/blog/calendar/calendar.htm  Sean Lin (林洵賢)

    以一个整数数组来保存各农历年的12个月大小月情况,以及闰月月份,闰月大小月,通过查表方式,计算农历日期。

    例:1900年的数据为 &H4BD8,用二进制表示:

以字为单位。

前12个bit,依次表示1-12月份的大小月,1为大月30天,0为小月29天

后4bit分为两种情况:

  1、闰月的月份(如1000,二进制转为十进制为8,表示该年闰八月)

  2、前一年闰月的大小月标志(二进制0000表示闰小月,二进制1111表示闰大月)

         闰月大小月与当前年份不在一起,而是在下一年的数据中,但不会产生冲突,是因为相邻两年,不可能同为闰月年。

编程思路:

    取给定农历与年初正月初一的天数,再在年初公历日期的基础上,加上相差的天数,取得新的公历日期即可;如果要由公历得到农历,则反一下即可。


  • VBA类代码:
  1. '
  2. '根据农历年月日取对应公历日期 类模块
  3. ' (By 漠石 mostone@hotmail.com)
  4. '
  5. ' 本类只有一个公用方法:
  6. ' Public Function GetDateFromLunar(y As Long, m As Long, d As Long, Optional isLeap As Boolean = False) As Date
  7. ' y: 1900 - 2100 200年
  8. ' m: 1 - 12 月份
  9. ' d: 1 - 30,如果是小月,并且传入了30,则返回下一农历月第一天的公历
  10. ' isLeap: 是否为闰月
  11. '
  12. '==========================================================================================
  13. ' 注:本模块的数据及代码参照自:http://s.o4u.com/host/blog/calendar/calendar.htm
  14. ' 以下为原作者信息:
  15. ' ***************************************
  16. ' 農曆月曆&世界時間 DHTML 程式 (台灣版)
  17. ' ***************************************
  18. ' 最後修改: 2009 年 3 月 20 日
  19. '
  20. '
  21. '如果您覺得這個程式不錯,您可以自由轉寄給親朋好友分享。自由使
  22. '用範圍: 學校、學會、公會、公司內部、程式研究、個人網站供人查
  23. '詢使用?
  24. '
  25. 'Open Source 不代表放棄著作權,任何形式之引用或轉載前請來信告
  26. '知。如需於「商業或營利」目的中使用此部份之程式碼或資料,需取
  27. '得本人書面授權。
  28. '
  29. '最新版本與更新資訊於 http://sean.o4u.com/ap/calendar/ 公佈
  30. '
  31. '
  32. '  歡迎來信互相討論研究與指正誤謬
  33. ' 連絡方式:http://sean.o4u.com/contact/
  34. ' Sean Lin(林洵賢)
  35. ' 尊重他人創作?請勿刪除或變更此說明
  36. Option Explicit
  37. Private compressLunarInfo As Variant
  38. Private dateOfLunarYearBegin() As Date
  39. Private Const LUNAR_YEAR_START As Long = 1900
  40. Private Const LUNAR_YEAR_END As Long = 2100
  41. Private Const FL_M As Integer = 1
  42. Private Const FL_D As Integer = 31
  43. '#### 根据农历年月日返回公历日期
  44. Public Function GetDateFromLunar(ByVal y As Long, ByVal m As Long, ByVal d As Long, Optional ByVal isLeap As Boolean = False) As Date
  45. Dim sum As Long, leapMonth As Integer
  46. If y < LUNAR_YEAR_START Or y > LUNAR_YEAR_END Then
  47. Err.Raise Number:=6, description:="只接受 " & LUNAR_YEAR_START & " - " & LUNAR_YEAR_END & " 之间的年份"
  48. Exit Function
  49. End If
  50. If m < 1 Or m > 12 Then
  51. Err.Raise Number:=7, description:="只接受 1 - 12 之间的月份"
  52. Exit Function
  53. End If
  54. If d < 1 Or d > 30 Then
  55. Err.Raise Number:=8, description:="只接受 1 - 30 之间的日期"
  56. Exit Function
  57. End If
  58. If Not isLeap Then
  59. sum = GetMultiLunarMonthDays(y, m - 1) + d - 1
  60. Else
  61. leapMonth = GetLeapMonth(y)
  62. If leapMonth <> m Then
  63. Err.Raise Number:=9, description:="不是闰月"
  64. Exit Function
  65. End If
  66. sum = GetMultiLunarMonthDays(y, m) + d - 1
  67. End If
  68. GetDateFromLunar = DateAdd("d", sum, dateOfLunarYearBegin(y - LUNAR_YEAR_START))
  69. End Function
  70. '#### 类初始化,数据准备
  71. Private Sub Class_Initialize()
  72. Dim i As Integer, itemCount As Integer, sum As Long
  73. compressLunarInfo = Array( _
  74. &H4BD8&, &H4AE0&, &HA570&, &H54D5&, &HD260&, &HD950&, &H5554&, &H56AF&, &H9AD0&, &H55D2&, _
  75. &H4AE0&, &HA5B6&, &HA4D0&, &HD250&, &HD295&, &HB54F&, &HD6A0&, &HADA2&, &H95B0&, &H4977&, _
  76. &H497F&, &HA4B0&, &HB4B5&, &H6A50&, &H6D40&, &HAB54&, &H2B6F&, &H9570&, &H52F2&, &H4970&, _
  77. &H6566&, &HD4A0&, &HEA50&, &H6A95&, &H5ADF&, &H2B60&, &H86E3&, &H92EF&, &HC8D7&, &HC95F&, _
  78. &HD4A0&, &HD8A6&, &HB55F&, &H56A0&, &HA5B4&, &H25DF&, &H92D0&, &HD2B2&, &HA950&, &HB557&, _
  79. &H6CA0&, &HB550&, &H5355&, &H4DAF&, &HA5B0&, &H4573&, &H52BF&, &HA9A8&, &HE950&, &H6AA0&, _
  80. &HAEA6&, &HAB50&, &H4B60&, &HAAE4&, &HA570&, &H5260&, &HF263&, &HD950&, &H5B57&, &H56A0&, _
  81. &H96D0&, &H4DD5&, &H4AD0&, &HA4D0&, &HD4D4&, &HD250&, &HD558&, &HB540&, &HB6A0&, &H95A6&, _
  82. &H95BF&, &H49B0&, &HA974&, &HA4B0&, &HB27A&, &H6A50&, &H6D40&, &HAF46&, &HAB60&, &H9570&, _
  83. &H4AF5&, &H4970&, &H64B0&, &H74A3&, &HEA50&, &H6B58&, &H5AC0&, &HAB60&, &H96D5&, &H92E0&, _
  84. &HC960&, &HD954&, &HD4A0&, &HDA50&, &H7552&, &H56A0&, &HABB7&, &H25D0&, &H92D0&, &HCAB5&, _
  85. &HA950&, &HB4A0&, &HBAA4&, &HAD50&, &H55D9&, &H4BA0&, &HA5B0&, &H5176&, &H52BF&, &HA930&, _
  86. &H7954&, &H6AA0&, &HAD50&, &H5B52&, &H4B60&, &HA6E6&, &HA4E0&, &HD260&, &HEA65&, &HD530&, _
  87. &H5AA0&, &H76A3&, &H96D0&, &H4AFB&, &H4AD0&, &HA4D0&, &HD0B6&, &HD25F&, &HD520&, &HDD45&, _
  88. &HB5A0&, &H56D0&, &H55B2&, &H49B0&, &HA577&, &HA4B0&, &HAA50&, &HB255&, &H6D2F&, &HADA0&, _
  89. &H4B63&, &H937F&, &H49F8&, &H4970&, &H64B0&, &H68A6&, &HEA5F&, &H6B20&, &HA6C4&, &HAAEF&, _
  90. &H92E0&, &HD2E3&, &HC960&, &HD557&, &HD4A0&, &HDA50&, &H5D55&, &H56A0&, &HA6D0&, &H55D4&, _
  91. &H52D0&, &HA9B8&, &HA950&, &HB4A0&, &HB6A6&, &HAD50&, &H55A0&, &HABA4&, &HA5B0&, &H52B0&, _
  92. &HB273&, &H6930&, &H7337&, &H6AA0&, &HAD50&, &H4B55&, &H4B6F&, &HA570&, &H54E4&, &HD260&, _
  93. &HE968&, &HD520&, &HDAA0&, &H6AA6&, &H56DF&, &H4AE0&, &HA9D4&, &HA4D0&, &HD150&, &HF252&, _
  94. &HD520&)
  95. ' 取得各农历年的正月初一的公历日期
  96. itemCount = UBound(compressLunarInfo)
  97. ReDim dateOfLunarYearBegin(itemCount)
  98. dateOfLunarYearBegin(0) = DateSerial(LUNAR_YEAR_START, FL_M, FL_D)
  99. For i = 0 To itemCount - 1
  100. sum = GetMultiLunarMonthDays(i + LUNAR_YEAR_START, 12)
  101. dateOfLunarYearBegin(i + 1) = DateAdd("d", sum, dateOfLunarYearBegin(i))
  102. 'Debug.Print (i + LUNAR_YEAR_START + 1) & "年正月初一的公历日期:" & vbTab & dateOfLunarYearBegin(i + 1)
  103. Next i
  104. End Sub
  105. '#### 取得 y 年从农历正月初一到 m 月月底的总天数
  106. Private Function GetMultiLunarMonthDays(y As Long, m As Long) As Long
  107. Dim i As Integer, mask As Long, sum As Long, leapMonth As Integer
  108. If m < 1 Then
  109. GetMultiLunarMonthDays = 0
  110. Exit Function
  111. End If
  112. mask = &H8000&
  113. sum = 0
  114. i = 1
  115. ' 各正常月份天数累加
  116. While (i <= m) And (mask > &H8)
  117. sum = sum + GetLunarMonthDays(y, mask)
  118. mask = mask / 2
  119. i = i + 1
  120. Wend
  121. ' 闰月天数累加
  122. leapMonth = GetLeapMonth(y)
  123. If leapMonth > 0 And leapMonth < m Then
  124. sum = sum + GetLeapDays(y)
  125. End If
  126. GetMultiLunarMonthDays = sum
  127. End Function
  128. '#### 返回 y 年指定月份的天数
  129. Private Function GetLunarMonthDays(y As Long, ByVal mask As Long) As Long
  130. If (compressLunarInfo(y - LUNAR_YEAR_START) And mask) = mask Then
  131. GetLunarMonthDays = 30
  132. Else
  133. GetLunarMonthDays = 29
  134. End If
  135. End Function
  136. '#### 返回 y 年闰月的天数
  137. Private Function GetLeapDays(y As Long) As Long
  138. If (compressLunarInfo(y - LUNAR_YEAR_START + 1) And &HF) = &HF Then
  139. GetLeapDays = 30
  140. Else
  141. GetLeapDays = 29
  142. End If
  143. End Function
  144. '#### 返回 y 年闰月的月份,1-12,没闰传回 0
  145. Private Function GetLeapMonth(y As Long) As Long
  146. Dim leapMonth As Long
  147. leapMonth = (compressLunarInfo(y - LUNAR_YEAR_START) And &HF)
  148. If leapMonth = &HF Then
  149. GetLeapMonth = 0
  150. Else
  151. GetLeapMonth = leapMonth
  152. End If
  153. End Function

-完-

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
农历闰月的推算
2020庚子鼠年将迎来“双闰年”和“双春年”
2023农历癸卯兔年,为什么会有384天?
时事地理 | 冷知识:中国的农历,不是阴历,更不是“lunar calendar”!
癸卯兔年,学习中国纪年历法。
“闰二月”、“闰年”、“闰月”分别用英文怎么说?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服