优化 农历

This commit is contained in:
Peleus 2024-02-01 11:22:20 +08:00
parent 302960077f
commit b50061c94f
5 changed files with 429 additions and 160 deletions

View File

@ -25,39 +25,44 @@
```go ```go
// 获取农历生肖 // 获取农历生肖
carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠 carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠
// 获取农历节日 // 获取农历节日
carbon.Parse("2021-02-12 13:14:15").Lunar().Festival() // 春节 carbon.Parse("2021-02-12 13:14:15").Lunar().Festival() // 春节
// 获取农历年月日时分秒 // 获取农历年份
carbon.Parse("2020-08-05 13:14:15").Lunar().DateTime() // 2020, 6, 16, 13, 14, 15
// 获取农历年月日
carbon.Parse("2020-08-05 13:14:15").Lunar().Date() // 2020, 6, 16
// 获取农历时分秒
carbon.Parse("2020-08-05 13:14:15").Lunar().Time() // 13, 14, 15
// 获取农历年年份
carbon.Parse("2020-08-05 13:14:15").Lunar().Year() // 2020 carbon.Parse("2020-08-05 13:14:15").Lunar().Year() // 2020
// 获取农历月 // 获取农历月份
carbon.Parse("2020-08-05 13:14:15").Lunar().Month() // 6 carbon.Parse("2020-08-05 13:14:15").Lunar().Month() // 6
// 获取农历闰月月份 // 获取农历闰月月份
carbon.Parse("2020-08-05 13:14:15").Lunar().LeapMonth() // 4 carbon.Parse("2020-08-05 13:14:15").Lunar().LeapMonth() // 4
// 获取农历日 // 获取农历日期
carbon.Parse("2020-08-05 13:14:15").Lunar().Day() // 16 carbon.Parse("2020-08-05 13:14:15").Lunar().Day() // 16
// 获取农历 YYYY-MM-DD HH::ii::ss 格式字符串 // 获取农历时辰
fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 2020-06-16 13:14:15 carbon.Parse("2020-08-05 13:14:15").Lunar().Hour() // 13
// 获取农历分钟
carbon.Parse("2020-08-05 13:14:15").Lunar().Minute() // 14
// 获取农历秒数
carbon.Parse("2020-08-05 13:14:15").Lunar().Second() // 15
// 获取农历日期时间字符串
carbon.Parse("2020-08-05 13:14:15").Lunar().String() // 2020-06-16 13:14:15
fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 2020-06-16 13:14:15
// 获取农历年字符串 // 获取农历年字符串
carbon.Parse("2020-08-05 13:14:15").Lunar().ToYearString() // 二零二零 carbon.Parse("2020-08-05 13:14:15").Lunar().ToYearString() // 二零二零
// 获取农历月字符串 // 获取农历月字符串
carbon.Parse("2020-08-05 13:14:15").Lunar().ToMonthString() // 六月 carbon.Parse("2020-08-05 13:14:15").Lunar().ToMonthString() // 六月
// 获取农历闰月字符串 // 获取农历闰月字符串
carbon.Parse("2020-04-23 13:14:15").Lunar().ToMonthString() // 闰四月 carbon.Parse("2020-04-23 13:14:15").Lunar().ToMonthString() // 闰四月
// 获取农历周字符串
carbon.Parse("2020-04-23 13:14:15").Lunar().ToWeekString() // 周四
// 获取农历天字符串 // 获取农历天字符串
carbon.Parse("2020-08-05 13:14:15").Lunar().ToDayString() // 十六 carbon.Parse("2020-08-05 13:14:15").Lunar().ToDayString() // 十六
// 获取农历日期字符串 // 获取农历日期字符串
carbon.Parse("2020-08-05 13:14:15").Lunar().ToDateString() // 二零二零年六月十六 carbon.Parse("2020-08-05 13:14:15").Lunar().ToDateString() // 二零二零年六月十六
// 是否是零值时间
carbon.Parse("0000-00-00 00:00:00").Lunar().IsZero() // true
carbon.Parse("2020-08-05 13:14:15").Lunar().IsZero() // false
// 是否是农历闰年 // 是否是农历闰年
carbon.Parse("2020-08-05 13:14:15").Lunar().IsLeapYear() // true carbon.Parse("2020-08-05 13:14:15").Lunar().IsLeapYear() // true
// 是否是农历闰月 // 是否是农历闰月

View File

@ -25,17 +25,9 @@
```go ```go
// 旧暦の干支を手に入れる // 旧暦の干支を手に入れる
carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠 carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠
// 旧暦の祝日を取得する // 旧暦の祝日を取得する
carbon.Parse("2021-02-12 13:14:15").Lunar().Festival() // 春节 carbon.Parse("2021-02-12 13:14:15").Lunar().Festival() // 春节
// 旧暦年月日取得時分秒
carbon.Parse("2020-08-05 13:14:15").Lunar().DateTime() // 2020, 6, 16, 13, 14, 15
// 旧暦年月日の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().Date() // 2020, 6, 16
// 旧暦取得時の分秒数
carbon.Parse("2020-08-05 13:14:15").Lunar().Time() // 13, 14, 15
// 旧正月の取得 // 旧正月の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().Year() // 2020 carbon.Parse("2020-08-05 13:14:15").Lunar().Year() // 2020
// 旧暦月の取得 // 旧暦月の取得
@ -44,20 +36,33 @@ carbon.Parse("2020-08-05 13:14:15").Lunar().Month() // 6
carbon.Parse("2020-08-05 13:14:15").Lunar().LeapMonth() // 4 carbon.Parse("2020-08-05 13:14:15").Lunar().LeapMonth() // 4
// 旧暦日の取得 // 旧暦日の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().Day() // 16 carbon.Parse("2020-08-05 13:14:15").Lunar().Day() // 16
// 旧暦 YYYY-MM-DD HH::ii::ss フォーマット文字列を取得します // 旧暦時刻の取得
fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 2020-06-16 13:14:15 carbon.Parse("2020-08-05 13:14:15").Lunar().Hour() // 13
// 旧暦分の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().Minute() // 14
// 旧暦の取得秒数
carbon.Parse("2020-08-05 13:14:15").Lunar().Second() // 15
// 旧暦日時文字列の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().String() // 2020-06-16 13:14:15
fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 2020-06-16 13:14:15
// 旧正月文字列の取得 // 旧正月文字列の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().ToYearString() // 二零二零 carbon.Parse("2020-08-05 13:14:15").Lunar().ToYearString() // 二零二零
// 旧暦月文字列の取得 // 旧暦月文字列の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().ToMonthString() // 六月 carbon.Parse("2020-08-05 13:14:15").Lunar().ToMonthString() // 六月
// 旧暦うるう月文字列の取得 // 旧暦うるう月文字列の取得
carbon.Parse("2020-04-23 13:14:15").Lunar().ToMonthString() // 闰四月 carbon.Parse("2020-04-23 13:14:15").Lunar().ToMonthString() // 闰四月
// 旧暦週文字列の取得
carbon.Parse("2020-04-23 13:14:15").Lunar().ToWeekString() // 周四
// 旧暦日文字列の取得 // 旧暦日文字列の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().ToDayString() // 十六 carbon.Parse("2020-08-05 13:14:15").Lunar().ToDayString() // 十六
// 旧暦日付文字列の取得 // 旧暦日付文字列の取得
carbon.Parse("2020-08-05 13:14:15").Lunar().ToDateString() // 二零二零年六月十六 carbon.Parse("2020-08-05 13:14:15").Lunar().ToDateString() // 二零二零年六月十六
// ゼロ値の時間ですか
carbon.Parse("0000-00-00 00:00:00").Lunar().IsZero() // true
carbon.Parse("2020-08-05 13:14:15").Lunar().IsZero() // false
// 旧暦うるう年かどうか // 旧暦うるう年かどうか
carbon.Parse("2020-08-05 13:14:15").Lunar().IsLeapYear() // true carbon.Parse("2020-08-05 13:14:15").Lunar().IsLeapYear() // true
// 旧暦うるう月かどうか // 旧暦うるう月かどうか

View File

@ -28,17 +28,9 @@ by [awesome-go](https://github.com/avelino/awesome-go#date-and-time "awesome-go"
```go ```go
// Get Lunar year of animal // Get Lunar year of animal
carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠 carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠
// Get lunar festival // Get lunar festival
carbon.Parse("2021-02-12 13:14:15").Lunar().Festival() // 春节 carbon.Parse("2021-02-12 13:14:15").Lunar().Festival() // 春节
// Get lunar year, month, day, hour, minute and second
carbon.Parse("2020-08-05 13:14:15").Lunar().DateTime() // 2020, 6, 16, 13, 14, 15
// Get lunar year, month and day
carbon.Parse("2020-08-05 13:14:15").Lunar().Date() // 2020, 6, 16
// Get lunar hour, minute and second
carbon.Parse("2020-08-05 13:14:15").Lunar().Time() // 13, 14, 15
// Get lunar year // Get lunar year
carbon.Parse("2020-08-05 13:14:15").Lunar().Year() // 2020 carbon.Parse("2020-08-05 13:14:15").Lunar().Year() // 2020
// Get lunar month // Get lunar month
@ -47,20 +39,33 @@ carbon.Parse("2020-08-05 13:14:15").Lunar().Month() // 6
carbon.Parse("2020-08-05 13:14:15").Lunar().LeapMonth() // 4 carbon.Parse("2020-08-05 13:14:15").Lunar().LeapMonth() // 4
// Get lunar day // Get lunar day
carbon.Parse("2020-08-05 13:14:15").Lunar().Day() // 16 carbon.Parse("2020-08-05 13:14:15").Lunar().Day() // 16
// Get lunar date as YYYY-MM-DD HH::ii::ss format string // Get lunar hour
fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 2020-06-16 13:14:15 carbon.Parse("2020-08-05 13:14:15").Lunar().Hour() // 13
// Get lunar minute
carbon.Parse("2020-08-05 13:14:15").Lunar().Minute() // 14
// Get lunar second
carbon.Parse("2020-08-05 13:14:15").Lunar().Second() // 15
// Get lunar date and time string
carbon.Parse("2020-08-05 13:14:15").Lunar().String() // 2020-06-16 13:14:15
fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 2020-06-16 13:14:15
// Get lunar year as string // Get lunar year as string
carbon.Parse("2020-08-05 13:14:15").Lunar().ToYearString() // 二零二零 carbon.Parse("2020-08-05 13:14:15").Lunar().ToYearString() // 二零二零
// Get lunar month as string // Get lunar month as string
carbon.Parse("2020-08-05 13:14:15").Lunar().ToMonthString() // 六月 carbon.Parse("2020-08-05 13:14:15").Lunar().ToMonthString() // 六月
// Get lunar leap month as string // Get lunar leap month as string
carbon.Parse("2020-04-23 13:14:15").Lunar().ToMonthString() // 闰四月 carbon.Parse("2020-04-23 13:14:15").Lunar().ToMonthString() // 闰四月
// Get lunar week as string
carbon.Parse("2020-04-23 13:14:15").Lunar().ToWeekString() // 周四
// Get lunar day as string // Get lunar day as string
carbon.Parse("2020-08-05 13:14:15").Lunar().ToDayString() // 十六 carbon.Parse("2020-08-05 13:14:15").Lunar().ToDayString() // 十六
// Get lunar date as string // Get lunar date as string
carbon.Parse("2020-08-05 13:14:15").Lunar().ToDateString() // 二零二零年六月十六 carbon.Parse("2020-08-05 13:14:15").Lunar().ToDateString() // 二零二零年六月十六
// Whether is a lunar zero time
carbon.Parse("0000-00-00 00:00:00").Lunar().IsZero() // true
carbon.Parse("2020-08-05 13:14:15").Lunar().IsZero() // false
// Whether is a lunar leap year // Whether is a lunar leap year
carbon.Parse("2020-08-05 13:14:15").Lunar().IsLeapYear() // true carbon.Parse("2020-08-05 13:14:15").Lunar().IsLeapYear() // true
// Whether is a lunar leap month // Whether is a lunar leap month

View File

@ -1,3 +1,4 @@
// Package lunar is part of the Carbon package.
package lunar package lunar
import ( import (
@ -13,6 +14,7 @@ var (
numbers = []string{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"} numbers = []string{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"}
months = []string{"正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊"} months = []string{"正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊"}
weeks = []string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"}
animals = []string{"猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"} animals = []string{"猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"}
festivals = map[string]string{ festivals = map[string]string{
@ -56,7 +58,7 @@ var (
} }
invalidYearError = func() error { invalidYearError = func() error {
return fmt.Errorf("invalid year, currently only 200 years from 1900 to 2100 are supported") return fmt.Errorf("invalid year, outside of range [1900,2100]")
} }
) )
@ -75,14 +77,17 @@ type Lunar struct {
} }
// FromGregorian creates a Gregorian instance from time.Time. // FromGregorian creates a Gregorian instance from time.Time.
// 从标准 time.Time 创建 Gregorian 结构体 // 从标准 time.Time 创建 Gregorian 实例
func FromGregorian(t time.Time) (g Gregorian) { func FromGregorian(t time.Time) (g Gregorian) {
if t.IsZero() {
return
}
g.Time = t g.Time = t
return return
} }
// FromLunar creates a Lunar instance from lunar datetime. // FromLunar creates a Lunar instance from lunar datetime.
// 从 农历日期 创建 Lunar 结构体 // 从 农历日期 创建 Lunar 实例
func FromLunar(year, month, day, hour, minute, second int, isLeapMonth bool) (l Lunar) { func FromLunar(year, month, day, hour, minute, second int, isLeapMonth bool) (l Lunar) {
l.year, l.month, l.day = year, month, day l.year, l.month, l.day = year, month, day
l.hour, l.minute, l.second = hour, minute, second l.hour, l.minute, l.second = hour, minute, second
@ -90,9 +95,12 @@ func FromLunar(year, month, day, hour, minute, second int, isLeapMonth bool) (l
return return
} }
// ToLunar converts Gregorian calendar to Lunar calendar. // ToLunar converts Gregorian instance to Lunar instance.
// 将 公历 转化为 农历 // 将 Gregorian 实例转化为 Lunar 实例
func (g Gregorian) ToLunar() (l Lunar) { func (g Gregorian) ToLunar() (l Lunar) {
if g.IsZero() {
return
}
daysInYear, daysInMonth, leapMonth := 365, 30, 0 daysInYear, daysInMonth, leapMonth := 365, 30, 0
if g.Year() < minYear || g.Year() > maxYear { if g.Year() < minYear || g.Year() > maxYear {
l.Error = invalidYearError() l.Error = invalidYearError()
@ -141,9 +149,12 @@ func (g Gregorian) ToLunar() (l Lunar) {
return return
} }
// ToGregorian converts Lunar calendar to Gregorian calendar. // ToGregorian converts Lunar instance to Gregorian instance.
// 将 农历 转化为 公历 // 将 Lunar 实例转化为 Gregorian 实例
func (l Lunar) ToGregorian() (g Gregorian) { func (l Lunar) ToGregorian() (g Gregorian) {
if l.IsZero() {
return
}
if l.year < minYear || l.year > maxYear { if l.year < minYear || l.year > maxYear {
g.Error = invalidYearError() g.Error = invalidYearError()
return return
@ -162,68 +173,10 @@ func (l Lunar) ToGregorian() (g Gregorian) {
return return
} }
func (g Gregorian) diffInDays(t time.Time) int {
return int(g.Time.Sub(t).Hours() / 24)
}
func (l Lunar) getOffsetInYear() int {
flag := false
clone, month, offset := l, 0, 0
for month = 1; month < l.month; month++ {
leapMonth := l.LeapMonth()
if !flag {
// 处理闰月
if leapMonth <= month && leapMonth > 0 {
offset += l.getDaysInLeapMonth()
flag = true
}
}
clone.month = month
offset += clone.getDaysInMonth()
}
return offset
}
func (l Lunar) getOffsetInMonth() int {
clone, year, offset := l, 0, 0
for year = minYear; year < l.year; year++ {
clone.year = year
offset += clone.getDaysInYear()
}
return offset
}
func (l Lunar) getDaysInYear() int {
var days = 348
for i := 0x8000; i > 0x8; i >>= 1 {
if (years[l.year-minYear] & i) != 0 {
days++
}
}
return days + l.getDaysInLeapMonth()
}
func (l Lunar) getDaysInMonth() int {
if (years[l.year-minYear] & (0x10000 >> uint(l.month))) != 0 {
return 30
}
return 29
}
func (l Lunar) getDaysInLeapMonth() int {
if l.LeapMonth() == 0 {
return 0
}
if years[l.year-minYear]&0x10000 != 0 {
return 30
}
return 29
}
// Animal gets lunar animal name like "猴". // Animal gets lunar animal name like "猴".
// 获取生肖 // 获取农历生肖
func (l Lunar) Animal() string { func (l Lunar) Animal() string {
if l.Error != nil { if l.IsZero() {
return "" return ""
} }
return animals[l.year%calendar.MonthsPerYear] return animals[l.year%calendar.MonthsPerYear]
@ -232,14 +185,14 @@ func (l Lunar) Animal() string {
// Festival gets lunar festival name like "春节". // Festival gets lunar festival name like "春节".
// 获取农历节日 // 获取农历节日
func (l Lunar) Festival() string { func (l Lunar) Festival() string {
if l.Error != nil { if l.IsZero() {
return "" return ""
} }
return festivals[fmt.Sprintf("%d-%d", l.month, l.day)] return festivals[fmt.Sprintf("%d-%d", l.month, l.day)]
} }
// Year gets lunar year like 2020. // Year gets lunar year like 2020.
// 获取农历年 // 获取农历年
func (l Lunar) Year() int { func (l Lunar) Year() int {
if l.Error != nil { if l.Error != nil {
return 0 return 0
@ -248,7 +201,7 @@ func (l Lunar) Year() int {
} }
// Month gets lunar month like 8. // Month gets lunar month like 8.
// 获取农历月 // 获取农历月
func (l Lunar) Month() int { func (l Lunar) Month() int {
if l.Error != nil { if l.Error != nil {
return 0 return 0
@ -256,17 +209,8 @@ func (l Lunar) Month() int {
return l.month return l.month
} }
// LeapMonth gets lunar leap month like 2.
// 获取农历闰月月份
func (l Lunar) LeapMonth() int {
if l.Error != nil {
return 0
}
return years[l.year-minYear] & 0xf
}
// Day gets lunar day like 5. // Day gets lunar day like 5.
// 获取农历日 // 获取农历日,如 5
func (l Lunar) Day() int { func (l Lunar) Day() int {
if l.Error != nil { if l.Error != nil {
return 0 return 0
@ -274,13 +218,61 @@ func (l Lunar) Day() int {
return l.day return l.day
} }
// ToYearString outputs a string in lunar year format like "二零二零". // Hour gets current hour like 13.
// 获取农历年字符串 // 获取农历时辰
func (l Lunar) ToYearString() string { func (l Lunar) Hour() int {
if l.Error != nil { if l.Error != nil {
return 0
}
return l.hour
}
// Minute gets current minute like 14.
// 获取农历分钟数
func (l Lunar) Minute() int {
if l.Error != nil {
return 0
}
return l.minute
}
// Second gets current second like 15.
// 获取农历秒数
func (l Lunar) Second() int {
if l.Error != nil {
return 0
}
return l.second
}
// LeapMonth gets lunar leap month like 2.
// 获取农历闰月月份,如 2
func (l Lunar) LeapMonth() int {
if l.Error != nil {
return 0
}
if l.year-minYear < 0 {
return 0
}
return years[l.year-minYear] & 0xf
}
// String implements Stringer interface and outputs a string in YYYY-MM-DD HH::ii::ss format like "2019-12-07 00:00:00".
// 实现 Stringer 接口, 输出 YYYY-MM-DD HH::ii::ss 格式字符串,如 "2019-12-07 00:00:00"
func (l Lunar) String() string {
if l.IsZero() {
return "" return ""
} }
year := fmt.Sprintf("%d", l.year) return fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d", l.year, l.month, l.day, l.hour, l.minute, l.second)
}
// ToYearString outputs a string in lunar year format like "二零二零".
// 获取农历年份字符串,如 "二零二零"
func (l Lunar) ToYearString() (year string) {
if l.IsZero() {
return
}
year = fmt.Sprintf("%d", l.year)
for index, number := range numbers { for index, number := range numbers {
year = strings.Replace(year, fmt.Sprintf("%d", index), number, -1) year = strings.Replace(year, fmt.Sprintf("%d", index), number, -1)
} }
@ -288,10 +280,10 @@ func (l Lunar) ToYearString() string {
} }
// ToMonthString outputs a string in lunar month format like "正月". // ToMonthString outputs a string in lunar month format like "正月".
// 获取农历月字符串 // 获取农历月字符串,如 "正月"
func (l Lunar) ToMonthString() (month string) { func (l Lunar) ToMonthString() (month string) {
if l.Error != nil { if l.IsZero() {
return "" return
} }
month = months[l.month-1] + "月" month = months[l.month-1] + "月"
if l.IsLeapMonth() { if l.IsLeapMonth() {
@ -300,10 +292,19 @@ func (l Lunar) ToMonthString() (month string) {
return return
} }
// ToWeekString outputs a string in week layout like "周一".
// 输出完整农历星期字符串,如 "周一"
func (l Lunar) ToWeekString() (month string) {
if l.IsZero() {
return ""
}
return weeks[l.ToGregorian().Week()]
}
// ToDayString outputs a string in lunar day format like "廿一". // ToDayString outputs a string in lunar day format like "廿一".
// 获取农历日字符串 // 获取农历日字符串,如 "廿一"
func (l Lunar) ToDayString() (day string) { func (l Lunar) ToDayString() (day string) {
if l.Error != nil { if l.IsZero() {
return return
} }
num := numbers[l.day%10] num := numbers[l.day%10]
@ -325,25 +326,28 @@ func (l Lunar) ToDayString() (day string) {
} }
// ToDateString outputs a string in lunar date format like "二零二零年腊月初五". // ToDateString outputs a string in lunar date format like "二零二零年腊月初五".
// 获取农历日期字符串 // 获取农历日期字符串,如 "二零二零年腊月初五"
func (l Lunar) ToDateString() string { func (l Lunar) ToDateString() string {
if l.Error != nil { if l.IsZero() {
return "" return ""
} }
return l.ToYearString() + "年" + l.ToMonthString() + l.ToDayString() return l.ToYearString() + "年" + l.ToMonthString() + l.ToDayString()
} }
// String outputs a string in YYYY-MM-DD HH::ii::ss format, implement Stringer interface. // IsZero reports whether is zero time.
// 输出 YYYY-MM-DD HH::ii::ss 格式字符串,实现 Stringer 接口 // 是否是农历零值时间
func (l Lunar) String() string { func (l Lunar) IsZero() bool {
if l.Error != nil { if l.Error != nil {
return "" return true
} }
return fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d", l.year, l.month, l.day, l.hour, l.minute, l.second) if l.year == 0 || l.month == 0 || l.day == 0 {
return true
}
return false
} }
// IsLeapYear reports whether is leap year. // IsLeapYear reports whether is leap year.
// 是否是闰年 // 是否是农历闰年
func (l Lunar) IsLeapYear() bool { func (l Lunar) IsLeapYear() bool {
if l.Error != nil { if l.Error != nil {
return false return false
@ -352,7 +356,7 @@ func (l Lunar) IsLeapYear() bool {
} }
// IsLeapMonth reports whether is leap month. // IsLeapMonth reports whether is leap month.
// 是否是闰月 // 是否是农历闰月
func (l Lunar) IsLeapMonth() bool { func (l Lunar) IsLeapMonth() bool {
if l.Error != nil { if l.Error != nil {
return false return false
@ -503,3 +507,61 @@ func (l Lunar) IsPigYear() bool {
} }
return false return false
} }
func (g Gregorian) diffInDays(t time.Time) int {
return int(g.Time.Sub(t).Hours() / 24)
}
func (l Lunar) getOffsetInYear() int {
flag := false
clone, month, offset := l, 0, 0
for month = 1; month < l.month; month++ {
leapMonth := l.LeapMonth()
if !flag {
// 处理闰月
if leapMonth <= month && leapMonth > 0 {
offset += l.getDaysInLeapMonth()
flag = true
}
}
clone.month = month
offset += clone.getDaysInMonth()
}
return offset
}
func (l Lunar) getOffsetInMonth() int {
clone, year, offset := l, 0, 0
for year = minYear; year < l.year; year++ {
clone.year = year
offset += clone.getDaysInYear()
}
return offset
}
func (l Lunar) getDaysInYear() int {
var days = 348
for i := 0x8000; i > 0x8; i >>= 1 {
if (years[l.year-minYear] & i) != 0 {
days++
}
}
return days + l.getDaysInLeapMonth()
}
func (l Lunar) getDaysInMonth() int {
if (years[l.year-minYear] & (0x10000 >> uint(l.month))) != 0 {
return 30
}
return 29
}
func (l Lunar) getDaysInLeapMonth() int {
if l.LeapMonth() == 0 {
return 0
}
if years[l.year-minYear]&0x10000 != 0 {
return 30
}
return 29
}

View File

@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestSolarToLunar(t *testing.T) { func TestGregorianToLunar(t *testing.T) {
type args struct { type args struct {
g Gregorian g Gregorian
} }
@ -44,6 +44,14 @@ func TestLunarToGregorian(t *testing.T) {
args args args args
want string want string
}{ }{
{
args: args{Lunar{}},
want: "",
},
{
args: args{FromLunar(0, 0, 0, 0, 0, 0, false)},
want: "",
},
{ {
args: args{FromLunar(2023, 12, 11, 0, 0, 0, false)}, args: args{FromLunar(2023, 12, 11, 0, 0, 0, false)},
want: "2024-01-21 00:00:00", want: "2024-01-21 00:00:00",
@ -80,6 +88,10 @@ func TestLunar_Animal(t *testing.T) {
args args args args
want string want string
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: "",
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: "", want: "",
@ -168,6 +180,10 @@ func TestLunar_Festival(t *testing.T) {
args args args args
want string want string
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: "",
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: "", want: "",
@ -232,6 +248,10 @@ func TestLunar_Year(t *testing.T) {
args args args args
want int want int
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: 0,
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: 0, want: 0,
@ -260,6 +280,10 @@ func TestLunar_Month(t *testing.T) {
args args args args
want int want int
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: 0,
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: 0, want: 0,
@ -320,34 +344,6 @@ func TestLunar_Month(t *testing.T) {
} }
} }
func TestLunar_LeapMonth(t *testing.T) {
type args struct {
g Gregorian
}
tests := []struct {
args args
want int
}{
{
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: 0,
},
{
args: args{FromGregorian(time.Date(2020, 4, 23, 0, 0, 0, 0, time.Local))},
want: 4,
},
{
args: args{FromGregorian(time.Date(2021, 7, 1, 0, 0, 0, 0, time.Local))},
want: 0,
},
}
for index, tt := range tests {
t.Run(strconv.Itoa(index), func(t *testing.T) {
assert.Equalf(t, tt.want, (tt.args.g).ToLunar().LeapMonth(), "args{%v}", tt.args.g)
})
}
}
func TestLunar_Day(t *testing.T) { func TestLunar_Day(t *testing.T) {
type args struct { type args struct {
g Gregorian g Gregorian
@ -356,6 +352,10 @@ func TestLunar_Day(t *testing.T) {
args args args args
want int want int
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: 0,
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: 0, want: 0,
@ -384,6 +384,122 @@ func TestLunar_Day(t *testing.T) {
} }
} }
func TestLunar_Hour(t *testing.T) {
type args struct {
g Gregorian
}
tests := []struct {
args args
want int
}{
{
args: args{FromGregorian(time.Time{})},
want: 0,
},
{
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: 0,
},
{
args: args{FromGregorian(time.Date(2020, 8, 19, 13, 14, 15, 0, time.Local))},
want: 13,
},
}
for index, tt := range tests {
t.Run(strconv.Itoa(index), func(t *testing.T) {
assert.Equalf(t, tt.want, (tt.args.g).ToLunar().Hour(), "args{%v}", tt.args.g)
})
}
}
func TestLunar_Minute(t *testing.T) {
type args struct {
g Gregorian
}
tests := []struct {
args args
want int
}{
{
args: args{FromGregorian(time.Time{})},
want: 0,
},
{
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: 0,
},
{
args: args{FromGregorian(time.Date(2020, 8, 19, 13, 14, 15, 0, time.Local))},
want: 14,
},
}
for index, tt := range tests {
t.Run(strconv.Itoa(index), func(t *testing.T) {
assert.Equalf(t, tt.want, (tt.args.g).ToLunar().Minute(), "args{%v}", tt.args.g)
})
}
}
func TestLunar_Second(t *testing.T) {
type args struct {
g Gregorian
}
tests := []struct {
args args
want int
}{
{
args: args{FromGregorian(time.Time{})},
want: 0,
},
{
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: 0,
},
{
args: args{FromGregorian(time.Date(2020, 8, 19, 13, 14, 15, 0, time.Local))},
want: 15,
},
}
for index, tt := range tests {
t.Run(strconv.Itoa(index), func(t *testing.T) {
assert.Equalf(t, tt.want, (tt.args.g).ToLunar().Second(), "args{%v}", tt.args.g)
})
}
}
func TestLunar_LeapMonth(t *testing.T) {
type args struct {
g Gregorian
}
tests := []struct {
args args
want int
}{
{
args: args{FromGregorian(time.Time{})},
want: 0,
},
{
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: 0,
},
{
args: args{FromGregorian(time.Date(2020, 4, 23, 0, 0, 0, 0, time.Local))},
want: 4,
},
{
args: args{FromGregorian(time.Date(2021, 7, 1, 0, 0, 0, 0, time.Local))},
want: 0,
},
}
for index, tt := range tests {
t.Run(strconv.Itoa(index), func(t *testing.T) {
assert.Equalf(t, tt.want, (tt.args.g).ToLunar().LeapMonth(), "args{%v}", tt.args.g)
})
}
}
func TestLunar_ToYearString(t *testing.T) { func TestLunar_ToYearString(t *testing.T) {
type args struct { type args struct {
g Gregorian g Gregorian
@ -392,6 +508,10 @@ func TestLunar_ToYearString(t *testing.T) {
args args args args
want string want string
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: "",
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: "", want: "",
@ -420,6 +540,10 @@ func TestLunar_ToMonthString(t *testing.T) {
args args args args
want string want string
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: "",
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: "", want: "",
@ -488,6 +612,54 @@ func TestLunar_ToMonthString(t *testing.T) {
} }
} }
func TestLunar_ToWeekString(t *testing.T) {
type args struct {
l Lunar
}
tests := []struct {
args args
want string
}{
{
args: args{Lunar{}},
want: "",
},
{
args: args{FromLunar(0, 0, 0, 0, 0, 0, false)},
want: "",
},
{
args: args{FromLunar(2023, 12, 20, 0, 0, 0, false)},
want: "周二",
},
{
args: args{FromLunar(2023, 12, 21, 0, 0, 0, false)},
want: "周三",
},
{
args: args{FromLunar(2023, 12, 22, 0, 0, 0, false)},
want: "周四",
},
{
args: args{FromLunar(2023, 12, 23, 0, 0, 0, false)},
want: "周五",
},
{
args: args{FromLunar(2023, 12, 24, 0, 0, 0, false)},
want: "周六",
},
{
args: args{FromLunar(2023, 12, 25, 0, 0, 0, false)},
want: "周日",
},
}
for index, tt := range tests {
t.Run(strconv.Itoa(index), func(t *testing.T) {
assert.Equalf(t, tt.want, (tt.args.l).ToWeekString(), "args{%v}", tt.args.l)
})
}
}
func TestLunar_ToDayString(t *testing.T) { func TestLunar_ToDayString(t *testing.T) {
type args struct { type args struct {
g Gregorian g Gregorian
@ -496,6 +668,10 @@ func TestLunar_ToDayString(t *testing.T) {
args args args args
want string want string
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: "",
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: "", want: "",
@ -576,6 +752,10 @@ func TestLunar_String(t *testing.T) {
args args args args
want string want string
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: "",
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: "", want: "",
@ -628,6 +808,10 @@ func TestLunar_ToDateString(t *testing.T) {
args args args args
want string want string
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: "",
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: "", want: "",
@ -696,6 +880,14 @@ func TestLunar_IsLeapYear(t *testing.T) {
args args args args
want bool want bool
}{ }{
{
args: args{FromGregorian(time.Time{})},
want: false,
},
{
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: false,
},
{ {
args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))},
want: false, want: false,