123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- package convert
- //Conversion of Gregorian Calendar to Lunar Calendar Tool Set
- //Thanks to the open source project provided by zhuqiyang, most of this tool is compiled from zhuqiyang
- import (
- "errors"
- "fmt"
- "math"
- "time"
- )
- type Convert struct {
- }
- var lunarInfomation = [200]int{
- 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-1909
- 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, //1910-1919
- 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, //1920-1929
- 0x06566, 0x0d4a0, 0x0ea50, 0x16a95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, //1930-1939
- 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, //1940-1949
- 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, //1950-1959
- 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, //1960-1969
- 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, //1970-1979
- 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, //1980-1989
- 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, //1990-1999
- 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, //2000-2009
- 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, //2010-2019
- 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029
- 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039
- 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, //2040-2049
- 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06aa0, 0x1a6c4, 0x0aae0, //2050-2059
- 0x092e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, //2060-2069
- 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, //2070-2079
- 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, //2080-2089
- 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, //2090-2099
- }
- var yearSum = map[int]int{
- 1900: 384, 1901: 354, 1902: 355, 1903: 383, 1904: 354, 1905: 355, 1906: 384, 1907: 354, 1908: 355, 1909: 384,
- 1910: 354, 1911: 384, 1912: 354, 1913: 354, 1914: 384, 1915: 354, 1916: 355, 1917: 384, 1918: 355, 1919: 384,
- 1920: 354, 1921: 354, 1922: 384, 1923: 354, 1924: 354, 1925: 385, 1926: 354, 1927: 355, 1928: 384, 1929: 354,
- 1930: 383, 1931: 354, 1932: 355, 1933: 384, 1934: 355, 1935: 354, 1936: 384, 1937: 354, 1938: 384, 1939: 354,
- 1940: 354, 1941: 384, 1942: 355, 1943: 354, 1944: 385, 1945: 354, 1946: 354, 1947: 384, 1948: 354, 1949: 384,
- 1950: 354, 1951: 355, 1952: 384, 1953: 354, 1954: 355, 1955: 384, 1956: 354, 1957: 383, 1958: 355, 1959: 354,
- 1960: 384, 1961: 355, 1962: 354, 1963: 384, 1964: 355, 1965: 353, 1966: 384, 1967: 355, 1968: 384, 1969: 354,
- 1970: 355, 1971: 384, 1972: 354, 1973: 354, 1974: 384, 1975: 354, 1976: 384, 1977: 354, 1978: 355, 1979: 384,
- 1980: 355, 1981: 354, 1982: 384, 1983: 354, 1984: 384, 1985: 354, 1986: 354, 1987: 384, 1988: 355, 1989: 355,
- 1990: 384, 1991: 354, 1992: 354, 1993: 383, 1994: 355, 1995: 384, 1996: 354, 1997: 355, 1998: 384, 1999: 354,
- 2000: 354, 2001: 384, 2002: 354, 2003: 355, 2004: 384, 2005: 354, 2006: 385, 2007: 354, 2008: 354, 2009: 384,
- 2010: 354, 2011: 354, 2012: 384, 2013: 355, 2014: 384, 2015: 354, 2016: 355, 2017: 384, 2018: 354, 2019: 354,
- 2020: 384, 2021: 354, 2022: 355, 2023: 384, 2024: 354, 2025: 384, 2026: 354, 2027: 354, 2028: 384, 2029: 355,
- 2030: 354, 2031: 384, 2032: 355, 2033: 384, 2034: 354, 2035: 354, 2036: 384, 2037: 354, 2038: 354, 2039: 384,
- 2040: 355, 2041: 355, 2042: 384, 2043: 354, 2044: 384, 2045: 354, 2046: 354, 2047: 384, 2048: 354, 2049: 355,
- 2050: 384, 2051: 355, 2052: 384, 2053: 354, 2054: 354, 2055: 383, 2056: 355, 2057: 354, 2058: 384, 2059: 355,
- 2060: 354, 2061: 384, 2062: 354, 2063: 384, 2064: 354, 2065: 355, 2066: 384, 2067: 354, 2068: 355, 2069: 384,
- 2070: 354, 2071: 384, 2072: 354, 2073: 354, 2074: 384, 2075: 355, 2076: 354, 2077: 384, 2078: 355, 2079: 354,
- 2080: 384, 2081: 354, 2082: 384, 2083: 354, 2084: 355, 2085: 384, 2086: 354, 2087: 355, 2088: 383, 2089: 354,
- 2090: 384, 2091: 354, 2092: 355, 2093: 384, 2094: 355, 2095: 354, 2096: 384, 2097: 354, 2098: 354, 2099: 384,
- }
- // GregorianToLunarCalendar 公历转农历
- // GregorianToLunarCalendar Gregorian to Lunar Calendar
- func (c Convert) GregorianToLunarCalendar(solarYear, solarMonth, solarDay int) [3]int {
- var date string = fmt.Sprintf("%04d-%02d-%02d", solarYear, solarMonth, solarDay)
- // 1900-1-31 时间戳
- var timestamp int64 = -2206425600
- timenumber, err := c.getTimestamp(date)
- if err != nil {
- fmt.Println("getTimestamp err = ", err)
- }
- days := int(math.Ceil(float64(timenumber-timestamp)/86400) + 1)
- var sum int = 0 // 农历天数之和
- var count int = len(yearSum) + 1900
- var lunarYear int
- for lunarYear = 1900; lunarYear < count; lunarYear++ {
- sum += yearSum[lunarYear]
- if sum >= days {
- break
- }
- }
- olddays := yearSum[lunarYear] - (sum - days)
- hex := lunarInfomation[lunarYear-1900]
- sumMonth := 0
- leapMonth := hex & 0xf
- isleap := false
- var i int
- var month int = 1
- for i = 0x08000; i >= 0x00010; i >>= 1 {
- if hex&i > 0 {
- sumMonth += 30
- } else {
- sumMonth += 29
- }
- if sumMonth >= olddays {
- break
- }
- if leapMonth == month {
- if hex&0xf0000 > 0 {
- sumMonth += 30
- } else {
- sumMonth += 29
- }
- isleap = true
- if sumMonth >= olddays {
- break
- }
- }
- month++
- }
- var currentMonthDays int
- if leapMonth == month && isleap {
- if hex&0xf0000 > 0 {
- currentMonthDays = 30
- } else {
- currentMonthDays = 29
- }
- } else {
- if hex&(0x08000>>(uint(month)-1)) > 0 {
- currentMonthDays = 30
- } else {
- currentMonthDays = 29
- }
- leapMonth = 0
- }
- day := currentMonthDays - (sumMonth - olddays)
- return [3]int{lunarYear, month, day}
- }
- // LunarToGregorian 农历转公历
- func (c Convert) LunarToGregorian(year, month, day int, leap bool) [3]int {
- var sum int = 0
- for i := 1900; i < year; i++ {
- sum += yearSum[i]
- }
- // 加上最后一年
- hex := lunarInfomation[year-1900]
- leapMonth := hex & 0xf
- lunarMonth := 1
- for i := 0x08000; i >= 0x00010; i >>= 1 {
- if month == lunarMonth {
- break
- }
- if hex&i > 0 {
- sum += 30
- } else {
- sum += 29
- }
- if leapMonth == lunarMonth {
- if hex&0xf0000 > 0 {
- sum += 30
- } else {
- sum += 29
- }
- }
- lunarMonth++
- }
- if month == leapMonth && leap {
- if hex&(0x08000>>(uint(lunarMonth)-1)) > 0 {
- sum += 30
- } else {
- sum += 29
- }
- }
- sum = sum + day // 这个和是农历天数的总和
- count := len(yearSum) + 1900
- solarSum := -30
- var solarYear int
- for solarYear = 1900; solarYear < count; solarYear++ {
- solarSum += c.GetSolarYearDays(solarYear)
- if solarSum >= sum {
- break
- }
- }
- sumMonth := c.GetSolarYearDays(solarYear) - (solarSum - sum)
- tempSum := 0
- solarMonth := 1
- for i := 0; i < 12; i++ {
- tempSum += c.GetSolarMonthDays(solarYear, solarMonth)
- if tempSum >= sumMonth {
- break
- }
- solarMonth++
- }
- lastMonth := c.GetSolarMonthDays(solarYear, solarMonth)
- solarDay := lastMonth - (tempSum - sumMonth)
- return [3]int{solarYear, solarMonth, solarDay}
- }
- // 获取时间戳
- func (Convert) getTimestamp(timeStr string) (int64, error) {
- loc, err := time.LoadLocation("Local")
- if err != nil {
- return -1, errors.New(fmt.Sprintf("time.LoadLocation %s", err))
- }
- Time, err := time.ParseInLocation("2006-01-02", timeStr, loc)
- if err != nil {
- return -1, errors.New(fmt.Sprintf("time.ParseInLocation %s", err))
- }
- return Time.Unix(), nil
- }
- // GetLunarYearDays 获取农历某年全年天数
- //Get the number of days in a year in the lunar calendar
- func (Convert) GetLunarYearDays(year int) int {
- hex := lunarInfomation[year-1900]
- sum := 0
- for i := 0x08000; i >= 0x00010; i >>= 1 {
- if hex&i > 0 {
- sum += 30
- } else {
- sum += 29
- }
- }
- if hex&0xf > 0 {
- if hex&0xf0000 > 0 {
- sum += 30
- } else {
- sum += 29
- }
- }
- return sum
- }
- // 获取个农历日期到1900年的所有天数
- // Get all the days from a lunar date to 1900
- func getLunarTotalDays(year, month, day int, leap bool) int {
- var sum int = 0
- for i := 1900; i < year; i++ {
- sum += yearSum[i]
- }
- // 加上最后一年
- hex := lunarInfomation[year-1900]
- leapMonth := hex & 0xf
- lunarMonth := 1
- for i := 0x08000; i >= 0x00010; i >>= 1 {
- if month == lunarMonth {
- break
- }
- if hex&i > 0 {
- sum += 30
- } else {
- sum += 29
- }
- if leapMonth == lunarMonth {
- if hex&0xf0000 > 0 {
- sum += 30
- } else {
- sum += 29
- }
- }
- lunarMonth++
- }
- if month == leapMonth && leap {
- if hex&(0x08000>>(uint(lunarMonth)-1)) > 0 {
- sum += 30
- } else {
- sum += 29
- }
- }
- return sum + day // 这个和是农历天数的总和
- }
- // GetDayGanZhiIndex Get the index value of the flow of heaven and earth, starting from 0
- func (Convert) GetDayGanZhiIndex(year, month, day int, leap bool) int {
- days := 43041 // 甲子日天数和
- differ := getLunarTotalDays(year, month, day, leap) - days
- index := differ % 60
- if index < 0 {
- index += 60
- }
- return index
- }
- // GetLunarMonthDays 获取农历某月天数
- //Get the number of days in a lunar month
- func (Convert) GetLunarMonthDays(year, month int, leapMonth bool) int {
- hex := lunarInfomation[year-1900]
- if leapMonth {
- if hex&0xf > 0 {
- if hex&0xf0000 > 0 {
- return 30
- } else {
- return 29
- }
- } else {
- return 0
- }
- } else {
- if hex&(0x08000>>(uint(month)-1)) > 0 {
- return 30
- } else {
- return 29
- }
- }
- }
- // GetLunarLeapMonth 获取农历某年闰月的月份,为零的时候没有闰月
- //Get the month of the leap month of a certain year in the lunar calendar, when it is zero, there is no leap month
- func (Convert) GetLunarLeapMonth(year int) int {
- return lunarInfomation[year-1900] & 0xf
- }
- // GetLunarLeapMonthDays 某年闰月天数
- //Leap month days in a year
- func (Convert) GetLunarLeapMonthDays(year int) int {
- hex := lunarInfomation[year-1900]
- if hex&0xf > 0 {
- if hex&0xf0000 > 0 {
- return 30
- } else {
- return 29
- }
- }
- return -1
- }
- // GetSolarYearDays 获取公历全年天数
- //Get the number of days in the Gregorian calendar year
- func (Convert) GetSolarYearDays(year int) int {
- if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
- return 366
- } else {
- return 365
- }
- }
- // GetSolarMonthDays 获取公历某月天数
- //Get the number of days in the Gregorian calendar month
- func (Convert) GetSolarMonthDays(year, month int) int {
- var days int
- if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
- days = 29
- } else {
- days = 28
- }
- 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}
- return monthDays[month]
- }
- // IsLeapYear 判断某年是否是闰年
- //Determine whether a year is a leap year
- func (Convert) IsLeapYear(year int) bool {
- if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
- return true
- } else {
- return false
- }
- }
- // GetLeapMonth 获取某年闰月月份
- //Get the leap month month of a certain year
- func (Convert) GetLeapMonth(year int) int {
- return lunarInfomation[year-1900] & 0xf
- }
|