convert.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. package convert
  2. //Conversion of Gregorian Calendar to Lunar Calendar Tool Set
  3. //Thanks to the open source project provided by zhuqiyang, most of this tool is compiled from zhuqiyang
  4. import (
  5. "errors"
  6. "fmt"
  7. "math"
  8. "time"
  9. )
  10. type Convert struct {
  11. }
  12. var lunarInfomation = [200]int{
  13. 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-1909
  14. 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, //1910-1919
  15. 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, //1920-1929
  16. 0x06566, 0x0d4a0, 0x0ea50, 0x16a95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, //1930-1939
  17. 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, //1940-1949
  18. 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, //1950-1959
  19. 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, //1960-1969
  20. 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, //1970-1979
  21. 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, //1980-1989
  22. 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, //1990-1999
  23. 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, //2000-2009
  24. 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, //2010-2019
  25. 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029
  26. 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039
  27. 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, //2040-2049
  28. 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06aa0, 0x1a6c4, 0x0aae0, //2050-2059
  29. 0x092e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, //2060-2069
  30. 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, //2070-2079
  31. 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, //2080-2089
  32. 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, //2090-2099
  33. }
  34. var yearSum = map[int]int{
  35. 1900: 384, 1901: 354, 1902: 355, 1903: 383, 1904: 354, 1905: 355, 1906: 384, 1907: 354, 1908: 355, 1909: 384,
  36. 1910: 354, 1911: 384, 1912: 354, 1913: 354, 1914: 384, 1915: 354, 1916: 355, 1917: 384, 1918: 355, 1919: 384,
  37. 1920: 354, 1921: 354, 1922: 384, 1923: 354, 1924: 354, 1925: 385, 1926: 354, 1927: 355, 1928: 384, 1929: 354,
  38. 1930: 383, 1931: 354, 1932: 355, 1933: 384, 1934: 355, 1935: 354, 1936: 384, 1937: 354, 1938: 384, 1939: 354,
  39. 1940: 354, 1941: 384, 1942: 355, 1943: 354, 1944: 385, 1945: 354, 1946: 354, 1947: 384, 1948: 354, 1949: 384,
  40. 1950: 354, 1951: 355, 1952: 384, 1953: 354, 1954: 355, 1955: 384, 1956: 354, 1957: 383, 1958: 355, 1959: 354,
  41. 1960: 384, 1961: 355, 1962: 354, 1963: 384, 1964: 355, 1965: 353, 1966: 384, 1967: 355, 1968: 384, 1969: 354,
  42. 1970: 355, 1971: 384, 1972: 354, 1973: 354, 1974: 384, 1975: 354, 1976: 384, 1977: 354, 1978: 355, 1979: 384,
  43. 1980: 355, 1981: 354, 1982: 384, 1983: 354, 1984: 384, 1985: 354, 1986: 354, 1987: 384, 1988: 355, 1989: 355,
  44. 1990: 384, 1991: 354, 1992: 354, 1993: 383, 1994: 355, 1995: 384, 1996: 354, 1997: 355, 1998: 384, 1999: 354,
  45. 2000: 354, 2001: 384, 2002: 354, 2003: 355, 2004: 384, 2005: 354, 2006: 385, 2007: 354, 2008: 354, 2009: 384,
  46. 2010: 354, 2011: 354, 2012: 384, 2013: 355, 2014: 384, 2015: 354, 2016: 355, 2017: 384, 2018: 354, 2019: 354,
  47. 2020: 384, 2021: 354, 2022: 355, 2023: 384, 2024: 354, 2025: 384, 2026: 354, 2027: 354, 2028: 384, 2029: 355,
  48. 2030: 354, 2031: 384, 2032: 355, 2033: 384, 2034: 354, 2035: 354, 2036: 384, 2037: 354, 2038: 354, 2039: 384,
  49. 2040: 355, 2041: 355, 2042: 384, 2043: 354, 2044: 384, 2045: 354, 2046: 354, 2047: 384, 2048: 354, 2049: 355,
  50. 2050: 384, 2051: 355, 2052: 384, 2053: 354, 2054: 354, 2055: 383, 2056: 355, 2057: 354, 2058: 384, 2059: 355,
  51. 2060: 354, 2061: 384, 2062: 354, 2063: 384, 2064: 354, 2065: 355, 2066: 384, 2067: 354, 2068: 355, 2069: 384,
  52. 2070: 354, 2071: 384, 2072: 354, 2073: 354, 2074: 384, 2075: 355, 2076: 354, 2077: 384, 2078: 355, 2079: 354,
  53. 2080: 384, 2081: 354, 2082: 384, 2083: 354, 2084: 355, 2085: 384, 2086: 354, 2087: 355, 2088: 383, 2089: 354,
  54. 2090: 384, 2091: 354, 2092: 355, 2093: 384, 2094: 355, 2095: 354, 2096: 384, 2097: 354, 2098: 354, 2099: 384,
  55. }
  56. // GregorianToLunarCalendar 公历转农历
  57. // GregorianToLunarCalendar Gregorian to Lunar Calendar
  58. func (c Convert) GregorianToLunarCalendar(solarYear, solarMonth, solarDay int) [3]int {
  59. var date string = fmt.Sprintf("%04d-%02d-%02d", solarYear, solarMonth, solarDay)
  60. // 1900-1-31 时间戳
  61. var timestamp int64 = -2206425600
  62. timenumber, err := c.getTimestamp(date)
  63. if err != nil {
  64. fmt.Println("getTimestamp err = ", err)
  65. }
  66. days := int(math.Ceil(float64(timenumber-timestamp)/86400) + 1)
  67. var sum int = 0 // 农历天数之和
  68. var count int = len(yearSum) + 1900
  69. var lunarYear int
  70. for lunarYear = 1900; lunarYear < count; lunarYear++ {
  71. sum += yearSum[lunarYear]
  72. if sum >= days {
  73. break
  74. }
  75. }
  76. olddays := yearSum[lunarYear] - (sum - days)
  77. hex := lunarInfomation[lunarYear-1900]
  78. sumMonth := 0
  79. leapMonth := hex & 0xf
  80. isleap := false
  81. var i int
  82. var month int = 1
  83. for i = 0x08000; i >= 0x00010; i >>= 1 {
  84. if hex&i > 0 {
  85. sumMonth += 30
  86. } else {
  87. sumMonth += 29
  88. }
  89. if sumMonth >= olddays {
  90. break
  91. }
  92. if leapMonth == month {
  93. if hex&0xf0000 > 0 {
  94. sumMonth += 30
  95. } else {
  96. sumMonth += 29
  97. }
  98. isleap = true
  99. if sumMonth >= olddays {
  100. break
  101. }
  102. }
  103. month++
  104. }
  105. var currentMonthDays int
  106. if leapMonth == month && isleap {
  107. if hex&0xf0000 > 0 {
  108. currentMonthDays = 30
  109. } else {
  110. currentMonthDays = 29
  111. }
  112. } else {
  113. if hex&(0x08000>>(uint(month)-1)) > 0 {
  114. currentMonthDays = 30
  115. } else {
  116. currentMonthDays = 29
  117. }
  118. leapMonth = 0
  119. }
  120. day := currentMonthDays - (sumMonth - olddays)
  121. return [3]int{lunarYear, month, day}
  122. }
  123. // LunarToGregorian 农历转公历
  124. func (c Convert) LunarToGregorian(year, month, day int, leap bool) [3]int {
  125. var sum int = 0
  126. for i := 1900; i < year; i++ {
  127. sum += yearSum[i]
  128. }
  129. // 加上最后一年
  130. hex := lunarInfomation[year-1900]
  131. leapMonth := hex & 0xf
  132. lunarMonth := 1
  133. for i := 0x08000; i >= 0x00010; i >>= 1 {
  134. if month == lunarMonth {
  135. break
  136. }
  137. if hex&i > 0 {
  138. sum += 30
  139. } else {
  140. sum += 29
  141. }
  142. if leapMonth == lunarMonth {
  143. if hex&0xf0000 > 0 {
  144. sum += 30
  145. } else {
  146. sum += 29
  147. }
  148. }
  149. lunarMonth++
  150. }
  151. if month == leapMonth && leap {
  152. if hex&(0x08000>>(uint(lunarMonth)-1)) > 0 {
  153. sum += 30
  154. } else {
  155. sum += 29
  156. }
  157. }
  158. sum = sum + day // 这个和是农历天数的总和
  159. count := len(yearSum) + 1900
  160. solarSum := -30
  161. var solarYear int
  162. for solarYear = 1900; solarYear < count; solarYear++ {
  163. solarSum += c.GetSolarYearDays(solarYear)
  164. if solarSum >= sum {
  165. break
  166. }
  167. }
  168. sumMonth := c.GetSolarYearDays(solarYear) - (solarSum - sum)
  169. tempSum := 0
  170. solarMonth := 1
  171. for i := 0; i < 12; i++ {
  172. tempSum += c.GetSolarMonthDays(solarYear, solarMonth)
  173. if tempSum >= sumMonth {
  174. break
  175. }
  176. solarMonth++
  177. }
  178. lastMonth := c.GetSolarMonthDays(solarYear, solarMonth)
  179. solarDay := lastMonth - (tempSum - sumMonth)
  180. return [3]int{solarYear, solarMonth, solarDay}
  181. }
  182. // 获取时间戳
  183. func (Convert) getTimestamp(timeStr string) (int64, error) {
  184. loc, err := time.LoadLocation("Local")
  185. if err != nil {
  186. return -1, errors.New(fmt.Sprintf("time.LoadLocation %s", err))
  187. }
  188. Time, err := time.ParseInLocation("2006-01-02", timeStr, loc)
  189. if err != nil {
  190. return -1, errors.New(fmt.Sprintf("time.ParseInLocation %s", err))
  191. }
  192. return Time.Unix(), nil
  193. }
  194. // GetLunarYearDays 获取农历某年全年天数
  195. //Get the number of days in a year in the lunar calendar
  196. func (Convert) GetLunarYearDays(year int) int {
  197. hex := lunarInfomation[year-1900]
  198. sum := 0
  199. for i := 0x08000; i >= 0x00010; i >>= 1 {
  200. if hex&i > 0 {
  201. sum += 30
  202. } else {
  203. sum += 29
  204. }
  205. }
  206. if hex&0xf > 0 {
  207. if hex&0xf0000 > 0 {
  208. sum += 30
  209. } else {
  210. sum += 29
  211. }
  212. }
  213. return sum
  214. }
  215. // 获取个农历日期到1900年的所有天数
  216. // Get all the days from a lunar date to 1900
  217. func getLunarTotalDays(year, month, day int, leap bool) int {
  218. var sum int = 0
  219. for i := 1900; i < year; i++ {
  220. sum += yearSum[i]
  221. }
  222. // 加上最后一年
  223. hex := lunarInfomation[year-1900]
  224. leapMonth := hex & 0xf
  225. lunarMonth := 1
  226. for i := 0x08000; i >= 0x00010; i >>= 1 {
  227. if month == lunarMonth {
  228. break
  229. }
  230. if hex&i > 0 {
  231. sum += 30
  232. } else {
  233. sum += 29
  234. }
  235. if leapMonth == lunarMonth {
  236. if hex&0xf0000 > 0 {
  237. sum += 30
  238. } else {
  239. sum += 29
  240. }
  241. }
  242. lunarMonth++
  243. }
  244. if month == leapMonth && leap {
  245. if hex&(0x08000>>(uint(lunarMonth)-1)) > 0 {
  246. sum += 30
  247. } else {
  248. sum += 29
  249. }
  250. }
  251. return sum + day // 这个和是农历天数的总和
  252. }
  253. // GetDayGanZhiIndex Get the index value of the flow of heaven and earth, starting from 0
  254. func (Convert) GetDayGanZhiIndex(year, month, day int, leap bool) int {
  255. days := 43041 // 甲子日天数和
  256. differ := getLunarTotalDays(year, month, day, leap) - days
  257. index := differ % 60
  258. if index < 0 {
  259. index += 60
  260. }
  261. return index
  262. }
  263. // GetLunarMonthDays 获取农历某月天数
  264. //Get the number of days in a lunar month
  265. func (Convert) GetLunarMonthDays(year, month int, leapMonth bool) int {
  266. hex := lunarInfomation[year-1900]
  267. if leapMonth {
  268. if hex&0xf > 0 {
  269. if hex&0xf0000 > 0 {
  270. return 30
  271. } else {
  272. return 29
  273. }
  274. } else {
  275. return 0
  276. }
  277. } else {
  278. if hex&(0x08000>>(uint(month)-1)) > 0 {
  279. return 30
  280. } else {
  281. return 29
  282. }
  283. }
  284. }
  285. // GetLunarLeapMonth 获取农历某年闰月的月份,为零的时候没有闰月
  286. //Get the month of the leap month of a certain year in the lunar calendar, when it is zero, there is no leap month
  287. func (Convert) GetLunarLeapMonth(year int) int {
  288. return lunarInfomation[year-1900] & 0xf
  289. }
  290. // GetLunarLeapMonthDays 某年闰月天数
  291. //Leap month days in a year
  292. func (Convert) GetLunarLeapMonthDays(year int) int {
  293. hex := lunarInfomation[year-1900]
  294. if hex&0xf > 0 {
  295. if hex&0xf0000 > 0 {
  296. return 30
  297. } else {
  298. return 29
  299. }
  300. }
  301. return -1
  302. }
  303. // GetSolarYearDays 获取公历全年天数
  304. //Get the number of days in the Gregorian calendar year
  305. func (Convert) GetSolarYearDays(year int) int {
  306. if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
  307. return 366
  308. } else {
  309. return 365
  310. }
  311. }
  312. // GetSolarMonthDays 获取公历某月天数
  313. //Get the number of days in the Gregorian calendar month
  314. func (Convert) GetSolarMonthDays(year, month int) int {
  315. var days int
  316. if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
  317. days = 29
  318. } else {
  319. days = 28
  320. }
  321. monthDays := map[int]int{1: 31, 2: days, 3: 31, 4: 30, 5: 31, 6: 30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31}
  322. return monthDays[month]
  323. }
  324. // IsLeapYear 判断某年是否是闰年
  325. //Determine whether a year is a leap year
  326. func (Convert) IsLeapYear(year int) bool {
  327. if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
  328. return true
  329. } else {
  330. return false
  331. }
  332. }
  333. // GetLeapMonth 获取某年闰月月份
  334. //Get the leap month month of a certain year
  335. func (Convert) GetLeapMonth(year int) int {
  336. return lunarInfomation[year-1900] & 0xf
  337. }