diff --git a/README.cn.md b/README.cn.md index 07316b56..6543ed0a 100644 --- a/README.cn.md +++ b/README.cn.md @@ -71,7 +71,7 @@ carbon.SetDefault(carbon.Default{ // 将标准 time.Time 转换成 Carbon carbon.CreateFromStdTime(time.Now()) // 将 Carbon 转换成标准 time.Time -carbon.Now().ToStdTime() +carbon.Now().StdTime() ``` ##### 昨天、今天、明天 @@ -1360,8 +1360,9 @@ fmt.Printf("%d", person.Field8) // 1596604455999999999 目前支持的日历有 -* [中国农历](./calendar/lunar/README.cn.md "中国农历") * [儒略日/简化儒略日](./calendar/julian/README.cn.md "儒略日/简化儒略日") +* [中国农历](./calendar/lunar/README.cn.md "中国农历") +* [波斯历/伊朗历](./calendar/persian/README.cn.md "波斯历/伊朗历") ##### 国际化 @@ -1380,14 +1381,16 @@ fmt.Printf("%d", person.Field8) // 1596604455999999999 * [乌克兰语(uk)](./lang/uk.json "乌克兰语"): 由 [open-git](https://github.com/open-git "open-git") 翻译 * [罗马尼亚语(ro)](./lang/ro.json "罗马尼亚语"): 由 [DrOctavius](https://github.com/DrOctavius "DrOctavius") 翻译 * [印度尼西亚语(id)](./lang/id.json "印度尼西亚语"): 由 [justpoypoy](https://github.com/justpoypoy "justpoypoy") 翻译 +* [意大利语(it)](./lang/it.json "意大利语"): 由 [nicoloHevelop](https://github.com/justpoypoy "nicoloHevelop") 翻译 * [马来西亚巴哈马语(ms-MY)](./lang/ms-MY.json "马来西亚巴哈马语"): 由 [hollowaykeanho](https://github.com/hollowaykeanho "hollowaykeanho") 翻译 * [法语(fr)](./lang/fr.json "法语"): 由 [hollowaykeanho](https://github.com/hollowaykeanho "hollowaykeanho") 翻译 * [泰语(th)](./lang/th.json "泰语"): 由 [izcream](https://github.com/izcream "izcream") 翻译 * [瑞典语(se)](./lang/se.json "瑞典语"): 由 [jwanglof](https://github.com/jwanglof "jwanglof") 翻译 -* [伊朗语(fa)](./lang/fa.json "伊朗语"): 由 [erfanMomeniii](https://github.com/ErfanMomeniii "ErfanMomeniii") 翻译 +* [波斯语(fa)](./lang/fa.json "波斯语"): 由 [erfanMomeniii](https://github.com/ErfanMomeniii "ErfanMomeniii") 翻译 * [波兰语(nl)](./lang/nl.json "波兰语"): 由 [RemcoE33](https://github.com/RemcoE33 "RemcoE33") 翻译 * [越南语(vi)](./lang/vi.json "越南语"): 由 [culy247](https://github.com/culy247 "culy247") 翻译 * [印地语(hi)](./lang/hi.json "印地语"): 由 [chauhan17nitin](https://github.com/chauhan17nitin "chauhan17nitin") 翻译 +* [波兰语(pl)](./lang/pl.json "波兰语"): 由 [gouguoyin](https://github.com/gouguoyin "gouguoyin") 翻译 目前支持的方法有 diff --git a/README.jp.md b/README.jp.md index cd987870..cd3e3b6d 100644 --- a/README.jp.md +++ b/README.jp.md @@ -75,7 +75,7 @@ carbon.SetDefault(carbon.Default{ // 標準の time.Time を Carbon に変換します carbon.CreateFromStdTime(time.Now()) // Carbon を標準の time.Time に変換します -carbon.Now().ToStdTime() +carbon.Now().StdTime() ``` ##### 昨日、今日、明日 @@ -1360,8 +1360,9 @@ fmt.Printf("%d", person.Field8) // 1596604455999999999 現在サポートされているカレンダーは -* [中国の旧暦](./calendar/lunar/README.jp.md "中国の旧暦") * [儒略の日/簡略化儒略の日](./calendar/julian/README.jp.md "儒略日/简化儒略日") +* [中国の旧暦](./calendar/lunar/README.jp.md "中国の旧暦") +* [ペルシャ暦/イラン暦](./calendar/persian/README.jp.md "ペルシャ暦/イラン暦") ##### 国際化 @@ -1380,14 +1381,16 @@ fmt.Printf("%d", person.Field8) // 1596604455999999999 * [ウクライナ語(uk)](./lang/uk.json "ウクライナ語"):[open-git](https://github.com/open-git "open-git") から翻訳されます * [ルーマニア語(ro)](./lang/ro.json "ルーマニア語"): [DrOctavius](https://github.com/DrOctavius "DrOctavius") から翻訳されます * [インドネシア語(id)](./lang/id.json "インドネシア語"): [justpoypoy](https://github.com/justpoypoy "justpoypoy") から翻訳されます +* [イタリア語(it)](./lang/it.json "イタリア語"): [nicoloHevelop](https://github.com/hollowaykeanho "nicoloHevelop") から翻訳されます * [マレーシアバハマ語(ms-MY)](./lang/ms-MY.json "マレーシアバハマ語"): [hollowaykeanho](https://github.com/hollowaykeanho "hollowaykeanho") から翻訳されます * [フランス語(fr)](./lang/fr.json "フランス語"): [hollowaykeanho](https://github.com/hollowaykeanho "hollowaykeanho") から翻訳されます * [タイ語(th)](./lang/th.json "タイ語"): [izcream](https://github.com/izcream "izcream") から翻訳されます * [スウェーデン語(se)](./lang/se.json "スウェーデン語"): [jwanglof](https://github.com/jwanglof "jwanglof") から翻訳されます -* [イラン語(fa)](./lang/fa.json "イラン語"): [Iranian](https://github.com/Iranian "Iranian") から翻訳されます +* [ペルシア語(fa)](./lang/fa.json "ペルシア語"): [Iranian](https://github.com/Iranian "Iranian") から翻訳されます * [ポーランド語(nl)](./lang/nl.json "ポーランド語"): [RemcoE33](https://github.com/RemcoE33 "RemcoE33") から翻訳されます * [ベトナム語(vi)](./lang/vi.json "ベトナム語"): [culy247](https://github.com/culy247 "culy247") から翻訳されます * [ヒンディー語(hi)](./lang/hi.json "ヒンディー語"): [chauhan17nitin](https://github.com/chauhan17nitin "chauhan17nitin") から翻訳されます +* [ポーランド語(pl)](./lang/pl.json "ポーランド語"): [gouguoyin](https://github.com/gouguoyin "gouguoyin") から翻訳されます 現在サポートされている方法 diff --git a/README.md b/README.md index 06eceb24..91b54b75 100644 --- a/README.md +++ b/README.md @@ -71,10 +71,10 @@ carbon.SetDefault(carbon.Default{ ##### Convert between Carbon and Time ```go -// Convert standard Time.time into Carbon +// Convert standard Time.time to Carbon carbon.CreateFromStdTime(time.Now()) // Convert Carbon to standard Time.time -carbon.Now().ToStdTime() +carbon.Now().StdTime() ``` ##### Yesterday, today and tomorrow @@ -1355,8 +1355,9 @@ fmt.Printf("%d", person.Field8) // 1596604455999999999 The following calendars are supported -* [Chinese Lunar](./calendar/lunar/README.md "Chinese Lunar") * [Julian Day/Modified Julian Day](./calendar/julian/README.md "JD/MJD") +* [Chinese Lunar](./calendar/lunar/README.md "Chinese Lunar") +* [Persian/Jalaali](./calendar/persian/README.md "Persian/Jalaali") ##### I18n @@ -1379,16 +1380,18 @@ The following languages are supported * [Ukrainian(uk)](./lang/uk.json "Ukrainian"): translated by [open-git](https://github.com/open-git "open-git") * [Romanian(ro)](./lang/ro.json "Romanian"): translated by [DrOctavius](https://github.com/DrOctavius "DrOctavius") * [Indonesian(id)](./lang/id.json "Indonesian"): translated by [justpoypoy](https://github.com/justpoypoy "justpoypoy") +* [Italian(it)](../blob/master/lang/it.json "Italian"): translated by [nicoloHevelop](https://github.com/nicoloHevelop "nicoloHevelop") * [Bahasa Malaysia(ms-MY)](./lang/ms-MY.json "Bahasa Malaysia"): translated by [hollowaykeanho](https://github.com/hollowaykeanho "hollowaykeanho") * [French(fr)](./lang/fr.json "French"): translated by [hollowaykeanho](https://github.com/hollowaykeanho "hollowaykeanho") * [Thailand(th)](./lang/th.json "Thailand"): translated by [izcream](https://github.com/izcream "izcream") * [Swedish(se)](./lang/se.json "Swedish"): translated by [jwanglof](https://github.com/jwanglof "jwanglof") -* [Iranian(fa)](./lang/fa.json "Iranian"): translated by [erfanMomeniii](https://github.com/erfanMomeniii "erfanMomeniii") +* [Farsi(fa)](./lang/fa.json "Farsi"): translated by [erfanMomeniii](https://github.com/erfanMomeniii "erfanMomeniii") * [Dutch(nl)](./lang/nl.json "Dutch"): translated by [RemcoE33](https://github.com/RemcoE33 "RemcoE33") * [VietNamese(vi)](./lang/vi.json "VietNam"): translated by [culy247](https://github.com/culy247 "culy247") * [Hindi(hi)](./lang/hi.json "India"): translated by [chauhan17nitin](https://github.com/chauhan17nitin "chauhan17nitin") +* [Polish(pl)](./lang/pl.json "Polish"): translated by [gouguoyin](https://github.com/gouguoyin "gouguoyin") The following methods are supported diff --git a/calendar.go b/calendar.go index 04384d84..42e076f0 100755 --- a/calendar.go +++ b/calendar.go @@ -3,6 +3,7 @@ package carbon import ( "github.com/golang-module/carbon/v2/calendar/julian" "github.com/golang-module/carbon/v2/calendar/lunar" + "github.com/golang-module/carbon/v2/calendar/persian" ) // Lunar converts Carbon instance to Lunar instance. @@ -37,3 +38,19 @@ func CreateFromJulian(f float64) Carbon { t := julian.FromJulian(f).ToGregorian().Time return CreateFromStdTime(t) } + +// Persian converts Carbon instance to Persian instance. +// 将 Carbon 实例转化为 Persian 实例 +func (c Carbon) Persian() (j persian.Persian) { + if c.Error != nil { + return j + } + return persian.FromGregorian(c.StdTime()).ToPersian() +} + +// CreateFromPersian creates a Carbon instance from Persian date and time. +// 从 波斯日期 创建 Carbon 实例 +func CreateFromPersian(year, month, day, hour, minute, second int) Carbon { + t := persian.FromPersian(year, month, day, hour, minute, second).ToGregorian().Time + return CreateFromStdTime(t) +} diff --git a/calendar/gregorian.go b/calendar/gregorian.go index ffc03d24..65f8a82f 100644 --- a/calendar/gregorian.go +++ b/calendar/gregorian.go @@ -1,3 +1,4 @@ +// Package calendar is part of the Carbon package. package calendar import ( @@ -159,7 +160,7 @@ func (g Gregorian) Year() int { } // Month gets gregorian month like 8. -// 获取公历月 +// 获取公历月,如 8 func (g Gregorian) Month() int { if g.IsZero() { return 0 @@ -167,8 +168,17 @@ func (g Gregorian) Month() int { return int(g.Time.Month()) } +// Week gets gregorian week day like 0. +// 获取周 +func (g Gregorian) Week() int { + if g.IsZero() { + return 0 + } + return int(g.Time.Weekday()) +} + // Day gets gregorian day like 5. -// 获取公历日 +// 获取公历日,如 0 func (g Gregorian) Day() int { if g.IsZero() { return 0 @@ -177,7 +187,7 @@ func (g Gregorian) Day() int { } // Hour gets gregorian hour like 13. -// 获取公历小时 +// 获取公历小时,如 13 func (g Gregorian) Hour() int { if g.IsZero() { return 0 @@ -186,7 +196,7 @@ func (g Gregorian) Hour() int { } // Minute gets gregorian minute like 14. -// 获取公历分钟数 +// 获取公历分钟数,如 14 func (g Gregorian) Minute() int { if g.IsZero() { return 0 @@ -195,7 +205,7 @@ func (g Gregorian) Minute() int { } // Second gets gregorian second like 15. -// 获取公历秒数 +// 获取公历秒数,如 15 func (g Gregorian) Second() int { if g.IsZero() { return 0 @@ -209,8 +219,8 @@ func (g Gregorian) Location() *time.Location { return g.Time.Location() } -// String implements the interface Stringer for Gregorian struct. -// 实现 Stringer 接口 +// 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 (g Gregorian) String() string { if g.IsZero() { return "" diff --git a/calendar/gregorian_test.go b/calendar/gregorian_test.go index 63a3f836..e10680cc 100755 --- a/calendar/gregorian_test.go +++ b/calendar/gregorian_test.go @@ -56,6 +56,30 @@ func TestGregorian_Month(t *testing.T) { } } +func TestGregorian_Week(t *testing.T) { + type args struct { + g Gregorian + } + tests := []struct { + args args + want int + }{ + { + args: args{NewGregorian(time.Time{})}, + want: 0, + }, + { + args: args{NewGregorian(time.Date(2020, 8, 5, 13, 14, 15, 0, time.Local))}, + want: 3, + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, tt.args.g.Week(), "args(%v)", tt.args.g) + }) + } +} + func TestGregorian_Day(t *testing.T) { type args struct { g Gregorian diff --git a/calendar/julian/julian.go b/calendar/julian/julian.go index 52bd6224..477ce19c 100644 --- a/calendar/julian/julian.go +++ b/calendar/julian/julian.go @@ -1,3 +1,4 @@ +// Package julian is part of the Carbon package. package julian import ( @@ -33,6 +34,9 @@ type Julian struct { // FromGregorian creates a Gregorian instance from time.Time. // 从标准 time.Time 创建 Gregorian 实例 func FromGregorian(t time.Time) (g Gregorian) { + if t.IsZero() { + return + } g.Time = t return g } @@ -62,20 +66,24 @@ func FromJulian(f float64) (j Julian) { // 将 Gregorian 实例转化为 Julian 实例 func (g Gregorian) ToJulian() (j Julian) { if g.IsZero() { - return j + return } y := g.Year() m := g.Month() d := float64(g.Day()) + ((float64(g.Second())/60+float64(g.Minute()))/60+float64(g.Hour()))/24 n := 0 + f := false if y*372+m*31+int(d) >= 588829 { - n = y / 100 - n = 2 - n + n/4 + f = true } if m <= 2 { m += 12 y-- } + if f { + n = y / 100 + n = 2 - n + n/4 + } jd := float64(int(365.25*(float64(y)+4716))) + float64(int(30.6001*(float64(m)+1))) + d + float64(n) - 1524.5 return FromJulian(jd) } @@ -83,8 +91,8 @@ func (g Gregorian) ToJulian() (j Julian) { // ToGregorian converts Julian instance to Gregorian instance. // 将 Julian 实例转化为 Gregorian 实例 func (j Julian) ToGregorian() (g Gregorian) { - if j.jd == 0 || j.mjd == 0 { - return g + if j.IsZero() { + return } d := int(j.jd + 0.5) f := j.jd + 0.5 - float64(d) @@ -136,9 +144,18 @@ func (j Julian) MJD(precision ...int) float64 { return parseFloat64(j.mjd, decimalPrecision) } +// IsZero reports whether is zero time. +// 是否是零值时间 +func (j Julian) IsZero() bool { + if j.jd == 0 || j.mjd == 0 { + return true + } + return false +} + // parseFloat64 round to n decimal places // 四舍五入保留 n 位小数点 func parseFloat64(f float64, n int) float64 { - p := math.Pow10(n) - return math.Round(f*p) / p + p10 := math.Pow10(n) + return math.Round(f*p10) / p10 } diff --git a/calendar/julian/julian_test.go b/calendar/julian/julian_test.go index eaa58709..09339114 100644 --- a/calendar/julian/julian_test.go +++ b/calendar/julian/julian_test.go @@ -23,6 +23,10 @@ func TestGregorian_ToJulian(t *testing.T) { args: args{FromGregorian(time.Time{})}, want: want{FromJulian(0)}, }, + { + args: args{FromGregorian(time.Date(1800, 1, 1, 0, 0, 0, 0, time.Local))}, + want: want{FromJulian(2378496.5)}, + }, { args: args{FromGregorian(time.Date(2024, 1, 23, 0, 0, 0, 0, time.Local))}, want: want{FromJulian(2460332.5)}, @@ -96,6 +100,10 @@ func TestGregorian_JD(t *testing.T) { args args want float64 }{ + { + args: args{FromGregorian(time.Date(1800, 1, 1, 0, 0, 0, 0, time.Local))}, + want: 2378496.5, + }, { args: args{FromGregorian(time.Date(2024, 1, 23, 0, 0, 0, 0, time.Local))}, want: 2460332.5, diff --git a/calendar/lunar/README.cn.md b/calendar/lunar/README.cn.md index 395d96bf..a250a190 100644 --- a/calendar/lunar/README.cn.md +++ b/calendar/lunar/README.cn.md @@ -25,39 +25,44 @@ ```go // 获取农历生肖 carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠 - // 获取农历节日 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().Month() // 6 // 获取农历闰月月份 carbon.Parse("2020-08-05 13:14:15").Lunar().LeapMonth() // 4 -// 获取农历日日期 +// 获取农历日期 carbon.Parse("2020-08-05 13:14:15").Lunar().Day() // 16 -// 获取农历 YYYY-MM-DD HH::ii::ss 格式字符串 +// 获取农历时辰 +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().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().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 // 是否是农历闰月 diff --git a/calendar/lunar/README.jp.md b/calendar/lunar/README.jp.md index c0806074..9be361c6 100644 --- a/calendar/lunar/README.jp.md +++ b/calendar/lunar/README.jp.md @@ -25,17 +25,9 @@ ```go // 旧暦の干支を手に入れる carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠 - // 旧暦の祝日を取得する 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 // 旧暦月の取得 @@ -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().Day() // 16 -// 旧暦 YYYY-MM-DD HH::ii::ss フォーマット文字列を取得します +// 旧暦時刻の取得 +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().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().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 // 旧暦うるう月かどうか diff --git a/calendar/lunar/README.md b/calendar/lunar/README.md index f3c20ac2..6fefec26 100644 --- a/calendar/lunar/README.md +++ b/calendar/lunar/README.md @@ -28,17 +28,9 @@ by [awesome-go](https://github.com/avelino/awesome-go#date-and-time "awesome-go" ```go // Get Lunar year of animal carbon.Parse("2020-08-05 13:14:15").Lunar().Animal() // 鼠 - // Get 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 carbon.Parse("2020-08-05 13:14:15").Lunar().Year() // 2020 // 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 // Get lunar day 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 +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 carbon.Parse("2020-08-05 13:14:15").Lunar().ToYearString() // 二零二零 // Get lunar month as string carbon.Parse("2020-08-05 13:14:15").Lunar().ToMonthString() // 六月 // Get lunar leap month as string 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 carbon.Parse("2020-08-05 13:14:15").Lunar().ToDayString() // 十六 // Get lunar date as string 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 carbon.Parse("2020-08-05 13:14:15").Lunar().IsLeapYear() // true // Whether is a lunar leap month diff --git a/calendar/lunar/lunar.go b/calendar/lunar/lunar.go index c06bfbfb..c1da4f26 100644 --- a/calendar/lunar/lunar.go +++ b/calendar/lunar/lunar.go @@ -1,3 +1,4 @@ +// Package lunar is part of the Carbon package. package lunar import ( @@ -13,6 +14,7 @@ var ( numbers = []string{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"} months = []string{"正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊"} + weeks = []string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"} animals = []string{"猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"} festivals = map[string]string{ @@ -56,7 +58,7 @@ var ( } invalidYearError = func() error { - return fmt.Errorf("invalid year, year outside of range [1900,2100]") + return fmt.Errorf("invalid year, outside of range [1900,2100]") } ) @@ -77,6 +79,9 @@ type Lunar struct { // FromGregorian creates a Gregorian instance from time.Time. // 从标准 time.Time 创建 Gregorian 实例 func FromGregorian(t time.Time) (g Gregorian) { + if t.IsZero() { + return + } g.Time = t return } @@ -93,6 +98,9 @@ func FromLunar(year, month, day, hour, minute, second int, isLeapMonth bool) (l // ToLunar converts Gregorian instance to Lunar instance. // 将 Gregorian 实例转化为 Lunar 实例 func (g Gregorian) ToLunar() (l Lunar) { + if g.IsZero() { + return + } daysInYear, daysInMonth, leapMonth := 365, 30, 0 if g.Year() < minYear || g.Year() > maxYear { l.Error = invalidYearError() @@ -144,6 +152,9 @@ func (g Gregorian) ToLunar() (l Lunar) { // ToGregorian converts Lunar instance to Gregorian instance. // 将 Lunar 实例转化为 Gregorian 实例 func (l Lunar) ToGregorian() (g Gregorian) { + if l.IsZero() { + return + } if l.year < minYear || l.year > maxYear { g.Error = invalidYearError() return @@ -162,68 +173,10 @@ func (l Lunar) ToGregorian() (g Gregorian) { 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 "猴". -// 获取生肖 +// 获取农历生肖 func (l Lunar) Animal() string { - if l.Error != nil { + if l.IsZero() { return "" } return animals[l.year%calendar.MonthsPerYear] @@ -232,14 +185,14 @@ func (l Lunar) Animal() string { // Festival gets lunar festival name like "春节". // 获取农历节日 func (l Lunar) Festival() string { - if l.Error != nil { + if l.IsZero() { return "" } return festivals[fmt.Sprintf("%d-%d", l.month, l.day)] } // Year gets lunar year like 2020. -// 获取农历年 +// 获取农历年份 func (l Lunar) Year() int { if l.Error != nil { return 0 @@ -248,7 +201,7 @@ func (l Lunar) Year() int { } // Month gets lunar month like 8. -// 获取农历月 +// 获取农历月份 func (l Lunar) Month() int { if l.Error != nil { return 0 @@ -256,31 +209,70 @@ func (l Lunar) Month() int { return l.month } -// LeapMonth gets lunar leap month like 2. -// 获取农历闰月月份 -func (l Lunar) LeapMonth() int { +// Day gets lunar day like 5. +// 获取农历日,如 5 +func (l Lunar) Day() int { if l.Error != nil { return 0 } - return years[l.year-minYear] & 0xf + return l.day } -// Day gets lunar day like 5. -// 获取农历日 -func (l Lunar) Day() int { +// Hour gets current hour like 13. +// 获取农历时辰 +func (l Lunar) Hour() int { if l.Error != nil { return 0 } - return l.day + return l.hour } -// ToYearString outputs a string in lunar year format like "二零二零". -// 获取农历年字符串 -func (l Lunar) ToYearString() string { +// 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 "" } - 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 { 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 "正月". -// 获取农历月字符串 +// 获取农历月份字符串,如 "正月" func (l Lunar) ToMonthString() (month string) { - if l.Error != nil { - return "" + if l.IsZero() { + return } month = months[l.month-1] + "月" if l.IsLeapMonth() { @@ -300,10 +292,19 @@ func (l Lunar) ToMonthString() (month string) { 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 "廿一". -// 获取农历日字符串 +// 获取农历日字符串,如 "廿一" func (l Lunar) ToDayString() (day string) { - if l.Error != nil { + if l.IsZero() { return } num := numbers[l.day%10] @@ -325,25 +326,28 @@ func (l Lunar) ToDayString() (day string) { } // ToDateString outputs a string in lunar date format like "二零二零年腊月初五". -// 获取农历日期字符串 +// 获取农历日期字符串,如 "二零二零年腊月初五" func (l Lunar) ToDateString() string { - if l.Error != nil { + if l.IsZero() { return "" } return l.ToYearString() + "年" + l.ToMonthString() + l.ToDayString() } -// String outputs a string in YYYY-MM-DD HH::ii::ss format, implement Stringer interface. -// 输出 YYYY-MM-DD HH::ii::ss 格式字符串,实现 Stringer 接口 -func (l Lunar) String() string { +// IsZero reports whether is zero time. +// 是否是农历零值时间 +func (l Lunar) IsZero() bool { if l.Error != nil { - return "" + return true + } + if l.year == 0 || l.month == 0 || l.day == 0 { + return true } - return fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d", l.year, l.month, l.day, l.hour, l.minute, l.second) + return false } // IsLeapYear reports whether is leap year. -// 是否是闰年 +// 是否是农历闰年 func (l Lunar) IsLeapYear() bool { if l.Error != nil { return false @@ -352,7 +356,7 @@ func (l Lunar) IsLeapYear() bool { } // IsLeapMonth reports whether is leap month. -// 是否是闰月 +// 是否是农历闰月 func (l Lunar) IsLeapMonth() bool { if l.Error != nil { return false @@ -503,3 +507,61 @@ func (l Lunar) IsPigYear() bool { } 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 +} diff --git a/calendar/lunar/lunar_test.go b/calendar/lunar/lunar_test.go index 73916492..d2c4f0f7 100644 --- a/calendar/lunar/lunar_test.go +++ b/calendar/lunar/lunar_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestSolarToLunar(t *testing.T) { +func TestGregorian_ToLunar(t *testing.T) { type args struct { g Gregorian } @@ -36,7 +36,7 @@ func TestSolarToLunar(t *testing.T) { } } -func TestLunarToGregorian(t *testing.T) { +func TestLunar_ToGregorian(t *testing.T) { type args struct { l Lunar } @@ -44,6 +44,14 @@ func TestLunarToGregorian(t *testing.T) { args args 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)}, want: "2024-01-21 00:00:00", @@ -80,6 +88,10 @@ func TestLunar_Animal(t *testing.T) { args args want string }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, { args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, want: "", @@ -168,6 +180,10 @@ func TestLunar_Festival(t *testing.T) { args args want string }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, { args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, want: "", @@ -232,6 +248,10 @@ func TestLunar_Year(t *testing.T) { 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, @@ -260,6 +280,10 @@ func TestLunar_Month(t *testing.T) { 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, @@ -320,7 +344,7 @@ func TestLunar_Month(t *testing.T) { } } -func TestLunar_LeapMonth(t *testing.T) { +func TestLunar_Day(t *testing.T) { type args struct { g Gregorian } @@ -328,27 +352,67 @@ func TestLunar_LeapMonth(t *testing.T) { 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))}, + args: args{FromGregorian(time.Date(2020, 8, 19, 0, 0, 0, 0, time.Local))}, + want: 1, + }, + { + args: args{FromGregorian(time.Date(2020, 8, 20, 0, 0, 0, 0, time.Local))}, + want: 2, + }, + { + args: args{FromGregorian(time.Date(2020, 8, 21, 0, 0, 0, 0, time.Local))}, + want: 3, + }, + { + args: args{FromGregorian(time.Date(2020, 8, 22, 0, 0, 0, 0, time.Local))}, want: 4, }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.g).ToLunar().Day(), "args{%v}", tt.args.g) + }) + } +} + +func TestLunar_Hour(t *testing.T) { + type args struct { + g Gregorian + } + tests := []struct { + args args + want int + }{ { - args: args{FromGregorian(time.Date(2021, 7, 1, 0, 0, 0, 0, time.Local))}, + 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().LeapMonth(), "args{%v}", tt.args.g) + assert.Equalf(t, tt.want, (tt.args.g).ToLunar().Hour(), "args{%v}", tt.args.g) }) } } -func TestLunar_Day(t *testing.T) { +func TestLunar_Minute(t *testing.T) { type args struct { g Gregorian } @@ -356,30 +420,82 @@ func TestLunar_Day(t *testing.T) { 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, 0, 0, 0, 0, time.Local))}, - want: 1, + 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.Date(2020, 8, 20, 0, 0, 0, 0, time.Local))}, - want: 2, + args: args{FromGregorian(time.Time{})}, + want: 0, }, { - args: args{FromGregorian(time.Date(2020, 8, 21, 0, 0, 0, 0, time.Local))}, - want: 3, + args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, + want: 0, }, { - args: args{FromGregorian(time.Date(2020, 8, 22, 0, 0, 0, 0, time.Local))}, + 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().Day(), "args{%v}", tt.args.g) + assert.Equalf(t, tt.want, (tt.args.g).ToLunar().LeapMonth(), "args{%v}", tt.args.g) }) } } @@ -392,6 +508,10 @@ func TestLunar_ToYearString(t *testing.T) { args args want string }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, { args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, want: "", @@ -420,6 +540,10 @@ func TestLunar_ToMonthString(t *testing.T) { args args want string }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, { args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, 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) { type args struct { g Gregorian @@ -496,6 +668,10 @@ func TestLunar_ToDayString(t *testing.T) { args args want string }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, { args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, want: "", @@ -576,6 +752,10 @@ func TestLunar_String(t *testing.T) { args args want string }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, { args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, want: "", @@ -628,6 +808,10 @@ func TestLunar_ToDateString(t *testing.T) { args args want string }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, { args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, want: "", @@ -696,6 +880,14 @@ func TestLunar_IsLeapYear(t *testing.T) { args args 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))}, want: false, diff --git a/calendar/persian/README.cn.md b/calendar/persian/README.cn.md new file mode 100644 index 00000000..db7e4d4b --- /dev/null +++ b/calendar/persian/README.cn.md @@ -0,0 +1,59 @@ +# Carbon + +[![Carbon Release](https://img.shields.io/github/release/golang-module/carbon.svg)](https://github.com/golang-module/carbon/releases) +[![Go Test](https://github.com/golang-module/carbon/actions/workflows/test.yml/badge.svg)](https://github.com/golang-module/carbon/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/golang-module/carbon/v2)](https://goreportcard.com/report/github.com/golang-module/carbon/v2) +[![Go Coverage](https://codecov.io/gh/golang-module/carbon/branch/master/graph/badge.svg)](https://codecov.io/gh/golang-module/carbon) +[![Goproxy.cn](https://goproxy.cn/stats/github.com/golang-module/carbon/badges/download-count.svg)](https://goproxy.cn) +[![Carbon Doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/golang-module/carbon/v2) +[![License](https://img.shields.io/github/license/golang-module/carbon)](https://github.com/golang-module/carbon/blob/master/LICENSE) + +简体中文 | [English](README.md) | [日本語](README.jp.md) + +一个轻量级、语义化、对开发者友好的 golang 时间处理库,支持链式调用,已被 [awesome-go-cn](https://github.com/yinggaozhen/awesome-go-cn#日期和时间 "awesome-go-cn") 收录 + +[github.com/golang-module/carbon](https://github.com/golang-module/carbon "github.com/golang-module/carbon") + +[gitee.com/golang-module/carbon](https://gitee.com/golang-module/carbon "gitee.com/golang-module/carbon") + +#### 波斯历(伊朗历) + +##### 将 `公历` 转换成 `波斯历` + +```go +// 获取波斯历年份 +carbon.Parse("2020-08-05 13:14:15").Persian().Year() // 1399 +// 获取波斯历月份 +carbon.Parse("2020-08-05 13:14:15").Persian().Month() // 5 +// 获取波斯历日期 +carbon.Parse("2020-08-05 13:14:15").Persian().Day() // 15 +// 获取波斯历小时 +carbon.Parse("2020-08-05 13:14:15").Persian().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() // 1399-05-15 13:14:15 +fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 1399-05-15 13:14:15 +// 获取波斯历月字符串 +carbon.Parse("2020-08-05 13:14:15").Persian().ToMonthString() // مرداد +// 获取波斯历周字符串 +carbon.Parse("2020-08-05 13:14:15").Persian().ToWeekString() // چهارشنبه + +// 是否是波斯历零值时间 +carbon.Parse("0000-00-00 00:00:00").Persian().IsZero() // true +carbon.Parse("2020-08-05 13:14:15").Persian().IsZero() // false + +// 是否是波斯历闰年 +carbon.Parse("2016-03-20 00:00:00").Persian().IsLeapYear() // true +carbon.Parse("2020-08-05 13:14:15").Persian().IsLeapYear() // false +``` + +##### 将 `波斯历` 转化成 `公历` + +```go +carbon.CreateFromPersian(1395, 1, 1, 0, 0, 0).ToDateTimeString() // 2016-03-20 00:00:00 +carbon.CreateFromPersian(1399, 5, 15, 13, 14, 15).ToDateTimeString() // 2020-08-05 13:14:15 +``` \ No newline at end of file diff --git a/calendar/persian/README.jp.md b/calendar/persian/README.jp.md new file mode 100644 index 00000000..4820fff7 --- /dev/null +++ b/calendar/persian/README.jp.md @@ -0,0 +1,59 @@ +# Carbon + +[![Carbon Release](https://img.shields.io/github/release/golang-module/carbon.svg)](https://github.com/golang-module/carbon/releases) +[![Go Test](https://github.com/golang-module/carbon/actions/workflows/test.yml/badge.svg)](https://github.com/golang-module/carbon/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/golang-module/carbon/v2)](https://goreportcard.com/report/github.com/golang-module/carbon/v2) +[![Go Coverage](https://codecov.io/gh/golang-module/carbon/branch/master/graph/badge.svg)](https://codecov.io/gh/golang-module/carbon) +[![Goproxy.cn](https://goproxy.cn/stats/github.com/golang-module/carbon/badges/download-count.svg)](https://goproxy.cn) +[![Carbon Doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/golang-module/carbon/v2) +[![License](https://img.shields.io/github/license/golang-module/carbon)](https://github.com/golang-module/carbon/blob/master/LICENSE) + +日本語 | [English](README.md) | [简体中文](README.cn.md) + +一个轻量级、语义化、对开发者友好的 golang 时间处理库,支持链式调用,已被 [awesome-go-cn](https://github.com/yinggaozhen/awesome-go-cn#日期和时间 "awesome-go-cn") 收录 + +[github.com/golang-module/carbon](https://github.com/golang-module/carbon "github.com/golang-module/carbon") + +[gitee.com/golang-module/carbon](https://gitee.com/golang-module/carbon "gitee.com/golang-module/carbon") + +#### ペルシア暦(イラン暦) + +##### `西暦` を `ペルシャ暦` に変換 + +```go +// ペルシャ暦の取得 +carbon.Parse("2020-08-05 13:14:15").Persian().Year() // 1399 +// ペルシャ暦月の取得 +carbon.Parse("2020-08-05 13:14:15").Persian().Month() // 5 +// ペルシャ暦の取得日 +carbon.Parse("2020-08-05 13:14:15").Persian().Day() // 15 +// ペルシャ暦時間の取得 +carbon.Parse("2020-08-05 13:14:15").Persian().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() // 1399-05-15 13:14:15 +fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 1399-05-15 13:14:15 +// ペルシア暦月文字列の取得 +carbon.Parse("2020-08-05 13:14:15").Persian().ToMonthString() // مرداد +// ペルシャ暦週文字列の取得 +carbon.Parse("2020-08-05 13:14:15").Persian().ToWeekString() // چهارشنبه + +// ペルシャ暦ゼロ時間かどうか +carbon.Parse("0000-00-00 00:00:00").Persian().IsZero() // true +carbon.Parse("2020-08-05 13:14:15").Persian().IsZero() // false + +// ペルシア暦閏年かどうか +carbon.Parse("2016-03-20 00:00:00").Persian().IsLeapYear() // true +carbon.Parse("2020-08-05 13:14:15").Persian().IsLeapYear() // false +``` + +##### ペルシャ暦を西暦に変換する + +```go +carbon.CreateFromPersian(1395, 1, 1, 0, 0, 0).ToDateTimeString() // 2016-03-20 00:00:00 +carbon.CreateFromPersian(1399, 5, 15, 13, 14, 15).ToDateTimeString() // 2020-08-05 13:14:15 +``` \ No newline at end of file diff --git a/calendar/persian/README.md b/calendar/persian/README.md new file mode 100644 index 00000000..9c6ee8ee --- /dev/null +++ b/calendar/persian/README.md @@ -0,0 +1,62 @@ +# Carbon + +[![Carbon Release](https://img.shields.io/github/release/golang-module/carbon.svg)](https://github.com/golang-module/carbon/releases) +[![Go Test](https://github.com/golang-module/carbon/actions/workflows/test.yml/badge.svg)](https://github.com/golang-module/carbon/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/golang-module/carbon/v2)](https://goreportcard.com/report/github.com/golang-module/carbon/v2) +[![Go Coverage](https://codecov.io/gh/golang-module/carbon/branch/master/graph/badge.svg)](https://codecov.io/gh/golang-module/carbon) +[![Goproxy.cn](https://goproxy.cn/stats/github.com/golang-module/carbon/badges/download-count.svg)](https://goproxy.cn) +[![Carbon Doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/golang-module/carbon/v2) +[![License](https://img.shields.io/github/license/golang-module/carbon)](https://github.com/golang-module/carbon/blob/master/LICENSE) + +English | [简体中文](README.cn.md) | [日本語](README.jp.md) + +#### Introduction + +A simple, semantic and developer-friendly golang package for time, has been included +by [awesome-go](https://github.com/avelino/awesome-go#date-and-time "awesome-go") + +[github.com/golang-module/carbon](https://github.com/golang-module/carbon "github.com/golang-module/carbon") + +[gitee.com/golang-module/carbon](https://gitee.com/golang-module/carbon "gitee.com/golang-module/carbon") + +#### Persian(Jalaali) Calendar + +##### Convert `Gregorian` calendar to `Persian` calendar + +```go +// Get persian year +carbon.Parse("2020-08-05 13:14:15").Persian().Year() // 1399 +// Get persian month +carbon.Parse("2020-08-05 13:14:15").Persian().Month() // 5 +// Get persian day +carbon.Parse("2020-08-05 13:14:15").Persian().Day() // 15 +// Get persian hour +carbon.Parse("2020-08-05 13:14:15").Persian().Hour() // 13 +// Get persian minute +carbon.Parse("2020-08-05 13:14:15").Lunar().Minute() // 14 +// Get persian second +carbon.Parse("2020-08-05 13:14:15").Lunar().Second() // 15 + +// Get persian date and time string +carbon.Parse("2020-08-05 13:14:15").Lunar().String() // 1399-05-15 13:14:15 +fmt.Printf("%s", carbon.Parse("2020-08-05 13:14:15").Lunar()) // 1399-05-15 13:14:15 +// // Get persian month as string +carbon.Parse("2020-08-05 13:14:15").Persian().ToMonthString() // مرداد +// // Get persian week as string +carbon.Parse("2020-08-05 13:14:15").Persian().ToWeekString() // چهارشنبه + +// Whether is a persian zero time +carbon.Parse("0000-00-00 00:00:00").Persian().IsZero() // true +carbon.Parse("2020-08-05 13:14:15").Persian().IsZero() // false + +// Whether is a persian leap year +carbon.Parse("2016-03-20 00:00:00").Persian().IsLeapYear() // true +carbon.Parse("2020-08-05 13:14:15").Persian().IsLeapYear() // false +``` + +##### Convert `Persian` calendar to `Gregorian` calendar + +```go +carbon.CreateFromPersian(1395, 1, 1, 0, 0, 0).ToDateTimeString() // 2016-03-20 00:00:00 +carbon.CreateFromPersian(1399, 5, 15, 13, 14, 15).ToDateTimeString() // 2020-08-05 13:14:15 +``` \ No newline at end of file diff --git a/calendar/persian/persian.go b/calendar/persian/persian.go new file mode 100644 index 00000000..dda34b86 --- /dev/null +++ b/calendar/persian/persian.go @@ -0,0 +1,246 @@ +package persian + +import ( + "fmt" + "math" + "time" + + "github.com/golang-module/carbon/v2/calendar" + "github.com/golang-module/carbon/v2/calendar/julian" +) + +type Month int + +const ( + Farvardin Month = 1 + iota + Ordibehesht + Khordad + Tir + Mordad + Shahrivar + Mehr + Aban + Azar + Dey + Bahman + Esfand +) + +var ( + minYear = 1097 + months = []string{"فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند"} + weeks = []string{"یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه"} + + invalidYearError = func() error { + return fmt.Errorf("invalid year, cannot exceed 1079") + } +) + +// Gregorian defines a Gregorian struct. +// 定义 Gregorian 结构体 +type Gregorian struct { + calendar.Gregorian +} + +// Persian defines a Persian struct. +// 定义 Persian 结构体 +type Persian struct { + year, month, day, hour, minute, second int + Error error +} + +// FromGregorian creates a Gregorian instance from time.Time. +// 从标准 time.Time 创建 Gregorian 实例 +func FromGregorian(t time.Time) (g Gregorian) { + g.Time = t + return +} + +// FromPersian creates a Persian instance from persian datetime. +// 从 波斯日期 创建 Persian 实例 +func FromPersian(year, month, day, hour, minute, second int) (p Persian) { + p.year, p.month, p.day = year, month, day + p.hour, p.minute, p.second = hour, minute, second + return p +} + +// ToPersian converts Gregorian instance to Persian instance. +// 将 Gregorian 实例转化为 Persian 实例 +func (g Gregorian) ToPersian() (p Persian) { + if g.IsZero() { + return + } + p.hour, p.minute, p.second = g.Hour(), g.Minute(), g.Second() + if g.Year() < minYear { + p.Error = invalidYearError() + return + } + gjdn := getGregorianJdn(g.Year(), g.Month(), g.Day()) + pjdn := getPersianJdn(475, 1, 1) + + diff := gjdn - pjdn + div := diff / 1029983 + mod := diff % 1029983 + + p.year = (2134*mod/366+2816*(mod%366)+2815)/1028522 + mod/366 + 1 + 2820*div + 474 + pjdn = getPersianJdn(p.year, 1, 1) + fjdn := float64(gjdn - pjdn + 1) + if fjdn <= 186 { + p.month = int(math.Ceil(fjdn / 31.0)) + } else { + p.month = int(math.Ceil((fjdn - 6) / 30.0)) + } + pjdn = getPersianJdn(p.year, p.month, 1) + p.day = gjdn - pjdn + 1 + return +} + +// ToGregorian converts Persian instance to Gregorian instance. +// 将 Persian 实例转化为 Gregorian 实例 +func (p Persian) ToGregorian() (g Gregorian) { + if p.IsZero() { + return + } + var year, month, day int + jdn := getPersianJdn(p.year, p.month, p.day) + + l := jdn + 68569 + n := 4 * l / 146097 + l = l - (146097*n+3)/4 + i := 4000 * (l + 1) / 1461001 + l = l - 1461*i/4 + 31 + j := 80 * l / 2447 + day = l - 2447*j/80 + l = j / 11 + month = j + 2 - 12*l + year = 100*(n-49) + i + l + + g.Time = time.Date(year, time.Month(month), day, p.hour, p.minute, p.second, 0, time.Local) + return +} + +// Year gets lunar year like 2020. +// 获取年份,如 2020 +func (p Persian) Year() int { + if p.Error != nil { + return 0 + } + return p.year +} + +// Month gets lunar month like 8. +// 获取月份,如 8 +func (p Persian) Month() int { + if p.Error != nil { + return 0 + } + return p.month +} + +// Day gets lunar day like 5. +// 获取日,如 5 +func (p Persian) Day() int { + if p.Error != nil { + return 0 + } + return p.day +} + +// Hour gets current hour like 13. +// 获取小时,如 13 +func (p Persian) Hour() int { + if p.Error != nil { + return 0 + } + return p.hour +} + +// Minute gets current minute like 14. +// 获取分钟数,如 14 +func (p Persian) Minute() int { + if p.Error != nil { + return 0 + } + return p.minute +} + +// Second gets current second like 15. +// 获取秒数,如 15 +func (p Persian) Second() int { + if p.Error != nil { + return 0 + } + return p.second +} + +// String implements Stringer interface and outputs a string in YYYY-MM-DD HH::ii::ss format like "1402-11-11 00:00:00". +// 实现 Stringer 接口, 输出 YYYY-MM-DD HH::ii::ss 格式字符串,如 "1402-11-11 00:00:00" +func (p Persian) String() string { + if p.IsZero() { + return "" + } + return fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d", p.year, p.month, p.day, p.hour, p.minute, p.second) +} + +// ToMonthString outputs a string in persian month format like "فروردین". +// 获取完整月份字符串,如 "فروردین" +func (p Persian) ToMonthString() (month string) { + if p.IsZero() { + return "" + } + return months[p.month-1] +} + +// ToWeekString outputs a string in week layout like "چهارشنبه". +// 输出完整星期字符串,如 "چهارشنبه" +func (p Persian) ToWeekString() (month string) { + if p.IsZero() { + return "" + } + return weeks[p.ToGregorian().Week()] +} + +// IsZero reports whether is zero time. +// 是否是零值时间 +func (p Persian) IsZero() bool { + if p.Error != nil { + return true + } + if p.year == 0 || p.month == 0 || p.day == 0 { + return true + } + return false +} + +// IsLeapYear reports whether is a leap year. +// 是否是闰年 +func (p Persian) IsLeapYear() bool { + if p.IsZero() { + return false + } + return (25*p.year+11)%33 < 8 +} + +// gets Julian day number in Persian calendar +// 获取波斯历儒略日计数 +func getPersianJdn(year, month, day int) int { + year = year - 473 + if year >= 0 { + year-- + } + epy := 474 + (year % 2820) + var md int + if month <= 7 { + md = (month - 1) * 31 + } else { + md = (month-1)*30 + 6 + } + return day + md + (epy*682-110)/2816 + (epy-1)*365 + year/2820*1029983 + 1948320 +} + +// gets Julian day number in Gregorian calendar +// 获取公历儒略日计数 +func getGregorianJdn(year, month, day int) int { + jdn := julian.FromGregorian(time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)).ToJulian().JD(0) + return int(jdn) +} diff --git a/calendar/persian/persian_test.go b/calendar/persian/persian_test.go new file mode 100755 index 00000000..d4300a2e --- /dev/null +++ b/calendar/persian/persian_test.go @@ -0,0 +1,478 @@ +package persian + +import ( + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestGregorian_ToPersian(t *testing.T) { + type args struct { + g Gregorian + } + tests := []struct { + args args + want string + }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, + { + args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, + want: "", + }, + { + args: args{FromGregorian(time.Date(1800, 1, 1, 0, 0, 0, 0, time.Local))}, + want: "1178-10-11 00:00:00", + }, + { + args: args{FromGregorian(time.Date(2024, 1, 1, 0, 0, 0, 0, time.Local))}, + want: "1402-10-11 00:00:00", + }, + { + args: args{FromGregorian(time.Date(2024, 8, 5, 12, 0, 0, 0, time.Local))}, + want: "1403-05-15 12:00:00", + }, + { + args: args{FromGregorian(time.Date(2024, 12, 31, 23, 59, 59, 0, time.Local))}, + want: "1403-10-11 23:59:59", + }, + { + args: args{FromGregorian(time.Date(2645, 3, 21, 0, 0, 0, 0, time.Local))}, + want: "2024-01-01 00:00:00", + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.g).ToPersian().String(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_ToGregorian(t *testing.T) { + type args struct { + p Persian + } + tests := []struct { + args args + want string + }{ + { + args: args{Persian{}}, + want: "", + }, + { + args: args{FromPersian(0, 0, 0, 0, 0, 0)}, + want: "", + }, + { + args: args{FromPersian(1395, 1, 1, 0, 0, 0)}, + want: "2016-03-20 00:00:00", + }, + { + args: args{FromPersian(1402, 10, 11, 0, 0, 0)}, + want: "2024-01-01 00:00:00", + }, + { + args: args{FromPersian(1403, 5, 15, 12, 0, 0)}, + want: "2024-08-05 12:00:00", + }, + { + args: args{FromPersian(1403, 10, 11, 23, 59, 59)}, + want: "2024-12-31 23:59:59", + }, + + { + args: args{FromPersian(2024, 1, 1, 0, 0, 0)}, + want: "2645-03-21 00:00:00", + }, + { + args: args{FromPersian(2100, 12, 31, 23, 59, 59)}, + want: "2722-03-22 23:59:59", + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.p).ToGregorian().String(), "args{%v}", tt.args.p) + }) + } +} + +func TestPersian_Year(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(2024, 1, 1, 0, 0, 0, 0, time.Local))}, + want: 1402, + }, + { + args: args{FromGregorian(time.Date(2024, 8, 5, 12, 0, 0, 0, time.Local))}, + want: 1403, + }, + { + args: args{FromGregorian(time.Date(2024, 12, 31, 23, 59, 59, 0, time.Local))}, + want: 1403, + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.g).ToPersian().Year(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_Month(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(2024, 1, 1, 0, 0, 0, 0, time.Local))}, + want: 10, + }, + { + args: args{FromGregorian(time.Date(2024, 8, 5, 12, 0, 0, 0, time.Local))}, + want: 5, + }, + { + args: args{FromGregorian(time.Date(2024, 12, 31, 23, 59, 59, 0, time.Local))}, + want: 10, + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.g).ToPersian().Month(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_Day(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(2024, 1, 1, 0, 0, 0, 0, time.Local))}, + want: 11, + }, + { + args: args{FromGregorian(time.Date(2024, 8, 5, 12, 0, 0, 0, time.Local))}, + want: 15, + }, + { + args: args{FromGregorian(time.Date(2024, 12, 31, 23, 59, 59, 0, time.Local))}, + want: 11, + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.g).ToPersian().Day(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_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).ToPersian().Hour(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_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).ToPersian().Minute(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_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).ToPersian().Second(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_ToMonthString(t *testing.T) { + type args struct { + g Gregorian + } + tests := []struct { + args args + want string + }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, + { + args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, + want: "", + }, + { + args: args{FromGregorian(time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local))}, + want: "دی", + }, + { + args: args{FromGregorian(time.Date(2020, 2, 1, 0, 0, 0, 0, time.Local))}, + want: "بهمن", + }, + { + args: args{FromGregorian(time.Date(2020, 3, 1, 0, 0, 0, 0, time.Local))}, + want: "اسفند", + }, + { + args: args{FromGregorian(time.Date(2020, 4, 1, 0, 0, 0, 0, time.Local))}, + want: "فروردین", + }, + { + args: args{FromGregorian(time.Date(2020, 5, 1, 0, 0, 0, 0, time.Local))}, + want: "اردیبهشت", + }, + { + args: args{FromGregorian(time.Date(2020, 6, 1, 0, 0, 0, 0, time.Local))}, + want: "خرداد", + }, + { + args: args{FromGregorian(time.Date(2020, 7, 1, 0, 0, 0, 0, time.Local))}, + want: "تیر", + }, + { + args: args{FromGregorian(time.Date(2020, 8, 1, 0, 0, 0, 0, time.Local))}, + want: "مرداد", + }, + { + args: args{FromGregorian(time.Date(2020, 9, 1, 0, 0, 0, 0, time.Local))}, + want: "شهریور", + }, + { + args: args{FromGregorian(time.Date(2020, 10, 1, 0, 0, 0, 0, time.Local))}, + want: "مهر", + }, + { + args: args{FromGregorian(time.Date(2020, 11, 1, 0, 0, 0, 0, time.Local))}, + want: "آبان", + }, + { + args: args{FromGregorian(time.Date(2020, 12, 1, 0, 0, 0, 0, time.Local))}, + want: "آذر", + }, + { + args: args{FromGregorian(time.Date(2021, 1, 1, 0, 0, 0, 0, time.Local))}, + want: "دی", + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.g).ToPersian().ToMonthString(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_ToWeekString(t *testing.T) { + type args struct { + g Gregorian + } + tests := []struct { + args args + want string + }{ + { + args: args{FromGregorian(time.Time{})}, + want: "", + }, + { + args: args{FromGregorian(time.Date(0, 0, 0, 0, 0, 0, 0, time.Local))}, + want: "", + }, + { + args: args{FromGregorian(time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local))}, + want: "چهارشنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 2, 1, 0, 0, 0, 0, time.Local))}, + want: "شنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 3, 1, 0, 0, 0, 0, time.Local))}, + want: "یکشنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 4, 1, 0, 0, 0, 0, time.Local))}, + want: "چهارشنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 5, 1, 0, 0, 0, 0, time.Local))}, + want: "جمعه", + }, + { + args: args{FromGregorian(time.Date(2020, 6, 1, 0, 0, 0, 0, time.Local))}, + want: "دوشنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 7, 1, 0, 0, 0, 0, time.Local))}, + want: "چهارشنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 8, 1, 0, 0, 0, 0, time.Local))}, + want: "شنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 9, 1, 0, 0, 0, 0, time.Local))}, + want: "سه شنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 10, 1, 0, 0, 0, 0, time.Local))}, + want: "پنجشنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 11, 1, 0, 0, 0, 0, time.Local))}, + want: "یکشنبه", + }, + { + args: args{FromGregorian(time.Date(2020, 12, 1, 0, 0, 0, 0, time.Local))}, + want: "سه شنبه", + }, + { + args: args{FromGregorian(time.Date(2021, 1, 1, 0, 0, 0, 0, time.Local))}, + want: "جمعه", + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.g).ToPersian().ToWeekString(), "args{%v}", tt.args.g) + }) + } +} + +func TestPersian_IsLeapYear(t *testing.T) { + type args struct { + p Persian + } + tests := []struct { + args args + want bool + }{ + { + args: args{Persian{}}, + want: false, + }, + { + args: args{FromPersian(0, 0, 0, 0, 0, 0)}, + want: false, + }, + { + args: args{FromPersian(1394, 1, 1, 0, 0, 0)}, + want: false, + }, + { + args: args{FromPersian(1395, 1, 1, 0, 0, 0)}, + want: true, + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, (tt.args.p).IsLeapYear(), "args{%v}", tt.args.p) + }) + } +} diff --git a/calendar_bench_test.go b/calendar_bench_test.go index 3915cf87..7199432a 100755 --- a/calendar_bench_test.go +++ b/calendar_bench_test.go @@ -27,3 +27,16 @@ func BenchmarkCarbon_CreateFromJulian(b *testing.B) { CreateFromJulian(60332) } } + +func BenchmarkCarbon_Persian(b *testing.B) { + now := Now() + for n := 0; n < b.N; n++ { + now.Persian() + } +} + +func BenchmarkCarbon_CreateFromPersian(b *testing.B) { + for n := 0; n < b.N; n++ { + CreateFromPersian(1455, 1, 1, 0, 0, 0) + } +} diff --git a/calendar_unit_test.go b/calendar_unit_test.go index b31f3b73..97184e29 100755 --- a/calendar_unit_test.go +++ b/calendar_unit_test.go @@ -1,7 +1,6 @@ package carbon import ( - "fmt" "strconv" "testing" @@ -101,13 +100,13 @@ func TestCarbon_Julian(t *testing.T) { } for index, tt := range tests { t.Run(strconv.Itoa(index), func(t *testing.T) { - assert.Equalf(t, tt.wantJD, tt.args.c.Julian().JD(), "Julian().JD()") - assert.Equalf(t, tt.wantMJD, tt.args.c.Julian().MJD(), "Julian().MJD()") + assert.Equalf(t, tt.wantJD, tt.args.c.Julian().JD(), "args{%v}", tt.args.c) + assert.Equalf(t, tt.wantMJD, tt.args.c.Julian().MJD(), "args{%v}", tt.args.c) }) } } -func TestCreateFromJulian(t *testing.T) { +func TestCarbon_CreateFromJulian(t *testing.T) { type args struct { j float64 } @@ -131,10 +130,74 @@ func TestCreateFromJulian(t *testing.T) { } } -func TestName(t *testing.T) { - r1 := Parse("2024-01-24 13:14:15").Julian().MJD() - fmt.Println(r1) +func TestCarbon_Persian(t *testing.T) { + type args struct { + c Carbon + } + tests := []struct { + args args + want string + }{ + { + args: args{Parse("xxx")}, + want: "", + }, + { + args: args{Parse("1800-01-01 00:00:00")}, + want: "1178-10-11 00:00:00", + }, + { + args: args{Parse("2020-08-05 13:14:15")}, + want: "1399-05-15 13:14:15", + }, + { + args: args{Parse("2024-01-01 00:00:00")}, + want: "1402-10-11 00:00:00", + }, + { + args: args{Parse("2024-08-05 12:00:00")}, + want: "1403-05-15 12:00:00", + }, + { + args: args{Parse("2024-12-31 23:59:59")}, + want: "1403-10-11 23:59:59", + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, tt.args.c.Persian().String(), "args{%v}", tt.args.c) + }) + } +} - r2 := CreateFromJulian(2460334.051563).ToDateTimeString() - fmt.Println(r2) +func TestCarbon_CreateFromPersian(t *testing.T) { + type args struct { + year, month, day, hour, minute, second int + } + tests := []struct { + args args + want string + }{ + { + args: args{year: 1178, month: 10, day: 11}, + want: "1800-01-01 00:00:00", + }, + { + args: args{year: 1402, month: 10, day: 11}, + want: "2024-01-01 00:00:00", + }, + { + args: args{year: 1403, month: 5, day: 15, hour: 12}, + want: "2024-08-05 12:00:00", + }, + { + args: args{year: 1403, month: 10, day: 11, hour: 23, minute: 59, second: 59}, + want: "2024-12-31 23:59:59", + }, + } + for index, tt := range tests { + t.Run(strconv.Itoa(index), func(t *testing.T) { + assert.Equalf(t, tt.want, CreateFromPersian(tt.args.year, tt.args.month, tt.args.day, tt.args.hour, tt.args.minute, tt.args.second).ToDateTimeString(), "args{%v}", tt.args) + }) + } } diff --git a/carbon.go b/carbon.go index 9d3a3b9d..7ff1e607 100644 --- a/carbon.go +++ b/carbon.go @@ -14,7 +14,7 @@ import ( // Version current version // 当前版本号 -const Version = "2.3.7" +const Version = "2.3.8" // timezone constants // 时区常量 @@ -143,6 +143,7 @@ const ( RssLayout = time.RFC1123Z RubyDateLayout = time.RubyDate UnixDateLayout = time.UnixDate + W3cLayout = RFC3339Layout RFC1036Layout = "Mon, 02 Jan 06 15:04:05 -0700" RFC1123Layout = time.RFC1123 diff --git a/constellation.go b/constellation.go index 80260631..542bd75d 100755 --- a/constellation.go +++ b/constellation.go @@ -43,7 +43,6 @@ func (c Carbon) Constellation() string { index = constellation.index } } - c.lang.rw.Lock() defer c.lang.rw.Unlock() if resources, ok := c.lang.resources["constellations"]; ok { diff --git a/difference.go b/difference.go index 84197cab..4673e40f 100755 --- a/difference.go +++ b/difference.go @@ -15,7 +15,6 @@ func (c Carbon) DiffInYears(carbon ...Carbon) int64 { if len(carbon) > 0 { end = carbon[0] } - dy, dm, dd := end.Year()-start.Year(), end.Month()-start.Month(), end.Day()-start.Day() if dm < 0 || (dm == 0 && dd < 0) { dy-- @@ -47,7 +46,6 @@ func (c Carbon) DiffInMonths(carbon ...Carbon) int64 { } startYear, startMonth, _ := c.Date() endYear, endMonth, _ := end.Date() - diffYear, diffMonth := endYear-startYear, endMonth-startMonth return int64(diffYear*MonthsPerYear + diffMonth) } diff --git a/encoding.go b/encoding.go index b3a9b69a..bbebc53f 100644 --- a/encoding.go +++ b/encoding.go @@ -5,8 +5,8 @@ import ( "fmt" ) -// MarshalJSON implements the interface Marshaler for Carbon struct. -// 实现 Marshaler 接口 +// MarshalJSON implements the json.Marshaler interface. +// 实现 json.Marshaler 接口 func (c Carbon) MarshalJSON() ([]byte, error) { if c.Error != nil { return nil, c.Error @@ -27,8 +27,8 @@ func (c Carbon) MarshalJSON() ([]byte, error) { return []byte(data), nil } -// UnmarshalJSON implements the interface Unmarshaler for Carbon struct. -// 实现 Unmarshaler 接口 +// UnmarshalJSON implements the json.Unmarshaler interface. +// 实现 json.Unmarshaler 接口 func (c *Carbon) UnmarshalJSON(b []byte) error { if c.Error != nil { return c.Error diff --git a/lang/de.json b/lang/de.json index 52f2a778..fa5d809b 100755 --- a/lang/de.json +++ b/lang/de.json @@ -1,4 +1,5 @@ { + "name": "German", "months": "Januar|Februar|März|April|Mai|Juni|Juli|August|September|Oktober|November|Dezember", "short_months": "Jan|Feb|Mär|Apr|Mai|Jun|Jul|Aug|Sep|Okt|Nov|Dez", "weeks": "Sonntag|Montag|Dienstag|Mittwoch|Donnerstag|Freitag|Samstag", diff --git a/lang/en.json b/lang/en.json index cac7b695..6dbc46a2 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1,4 +1,5 @@ { + "name": "English", "months": "January|February|March|April|May|June|July|August|September|October|November|December", "short_months": "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec", "weeks": "Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday", diff --git a/lang/es.json b/lang/es.json index 118562ab..3b8ac7d2 100755 --- a/lang/es.json +++ b/lang/es.json @@ -1,4 +1,5 @@ { + "name": "Spanish", "months": "Enero|Febrero|Marzo|Abril|Mayo|Junio|Julio|Agosto|Septiembre|Octubre|Noviembre|Diciembre", "short_months": "Ene|Feb|Mar|Abr|May|Jun|Jul|Ago|Sep|Oct|Nov|Dic", "weeks": "Domingo|Lunes|Martes|Miércoles|Jueves|Viernes|Sábado", diff --git a/lang/fa.json b/lang/fa.json index 8b2fa1cb..f5ffc2b8 100644 --- a/lang/fa.json +++ b/lang/fa.json @@ -1,4 +1,5 @@ { + "name": "Farsi", "months": "دسامبر|نوامبر|اکتبر|سپتامبر|اوت|ژوئیه|ژوئن|مه|آوریل|مارس|فوریه|ژانویه", "short_months": "دسامبر|نوامبر|اکتبر|سپتامبر|اوت|ژوئیه|ژوئن|مه|آوریل|مارس|فوریه|ژانویه", "weeks": "شنبه|جمعه|پنجشنبه|چهارشنبه|سه شنبه|دوشنبه|یکشنبه", diff --git a/lang/fr.json b/lang/fr.json index 77a91710..4fd0f57b 100755 --- a/lang/fr.json +++ b/lang/fr.json @@ -1,4 +1,5 @@ { + "name": "French", "months": "Janvier|Février|Mars|Avril|Mai|Juin|Juillet|Août|Septembre|Octobre|Novembre|Décembre", "short_months": "Janv|Févr|Mars|Avril|Mai|Juin|Juil|Août|Sept|Oct|Nov|Déc", "weeks": "Dimanche|Lundi|Mardi|Mercredi|Jeudi|Vendredi|Samedi", diff --git a/lang/hi.json b/lang/hi.json index 4aa4ba70..72b44bad 100644 --- a/lang/hi.json +++ b/lang/hi.json @@ -1,4 +1,5 @@ { + "name": "Hindi", "months": "जनवरी|फ़रवरी|मार्च|अप्रैल|मई|जून|जुलाई|अगस्त|सितंबर|अक्टूबर|नवंबर|दिसंबर", "short_months": "जन|फ़र|मार्च|अप्रैल|मई|जून|जुलाई|अगस्त|सितंबर|अक्टूबर|नवंबर|दिसंबर", "weeks": "रविवार|सोमवार|मंगलवार|बुधवार|गुरुवार|शुक्रवार|शनिवार", diff --git a/lang/id.json b/lang/id.json index f495ba49..e57fdfce 100755 --- a/lang/id.json +++ b/lang/id.json @@ -1,4 +1,5 @@ { + "name": "Indonesian", "months": "Januari|Februari|Maret|April|Mei|Juni|Juli|Agustus|September|Oktober|November|Desember", "short_months": "Jan|Feb|Mar|Apr|Mei|Jun|Jul|Agt|Sep|Okt|Nov|Des", "weeks": "Minggu|Senin|Selasa|Rabu|Kamis|Jumaat|Sabtu", diff --git a/lang/it.json b/lang/it.json index 386e2520..a2164f45 100644 --- a/lang/it.json +++ b/lang/it.json @@ -1,4 +1,5 @@ { + "name": "Italian", "months": "Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno|Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre", "short_months": "Gen|Feb|Mar|Apr|Mag|Giu|Lug|Ago|Set|Ott|Nov|Dic", "weeks": "Domenica|Lunedí|Martedí|Mercoledí|Giovedí|Venerdí|Sabato", diff --git a/lang/jp.json b/lang/jp.json index ae872741..60869383 100755 --- a/lang/jp.json +++ b/lang/jp.json @@ -1,4 +1,5 @@ { + "name": "Japanese", "months": "いちがつ|にがつ|さんがつ|しがつ|ごがつ|ろくがつ|しちがつ|はちがつ|くがつ|じゅうがつ|じゅういちがつ|じゅうにがつ", "short_months": "1がつ|2がつ|3がつ|4がつ|5がつ|6がつ|7がつ|8がつ|9がつ|10がつ|11がつ|12がつ", "weeks": "日曜日|月曜日|火曜日|水曜日|木曜日|金曜日|土曜日", diff --git a/lang/kr.json b/lang/kr.json index b7ba9bdb..978d3a88 100755 --- a/lang/kr.json +++ b/lang/kr.json @@ -1,4 +1,5 @@ { + "name": "Korean", "months": "일월|이월|삼월|사월|오월|유월|칠월|팔월|구월|시월|십일월|십이월", "short_months": "1월|2월|3월|4월|5월|6월|7월|8월|9월|10월|11월|12월", "weeks": "일요일|월요일|화요일|수요일|목요일|금요일|토요일", diff --git a/lang/ms-MY.json b/lang/ms-MY.json index dc53bfa9..49b2922d 100755 --- a/lang/ms-MY.json +++ b/lang/ms-MY.json @@ -1,4 +1,5 @@ { + "name": "Bahasa Malaysia", "months": "Januari|Februari|Mac|April|Mei|Jun|Julai|Ogos|September|Oktober|November|Disember", "short_months": "Jan|Feb|Mac|Apr|Mei|Jun|Jul|Ogs|Sep|Okt|Nov|Dis", "weeks": "Ahad|Isnin|Selasa|Rabu|Khamis|Jumaat|Sabtu", diff --git a/lang/nl.json b/lang/nl.json index 7fe761e3..d49ea2d2 100644 --- a/lang/nl.json +++ b/lang/nl.json @@ -1,4 +1,5 @@ { + "name": "Dutch", "months": "januari|februari|maart|april|mei|juni|juli|augustus|september|oktober|november|december", "short_months": "jan|feb|mrt|apr|mei|jun|jul|aug|sep|okt|nov|dec", "weeks": "Zondag|Maandag|Dinsdag|Woensdag|Donderdag|Vrijdag|Zaterdag|Zondag", diff --git a/lang/pl.json b/lang/pl.json new file mode 100755 index 00000000..03ba9d98 --- /dev/null +++ b/lang/pl.json @@ -0,0 +1,21 @@ +{ + "name": "Polish", + "months": "stycznia|lutego|marca|kwietnia|maja|czerwca|lipca|sierpnia|września|października|listopada|grudnia", + "short_months": "sty|lut|mar|kwi|maj|cze|lip|sie|wrz|paź|lis|gru", + "weeks": "niedziela|poniedziałek|wtorek|środa|czwartek|piątek|sobota", + "short_weeks": "ndz|pon|wt|śr|czw|pt|sob", + "seasons": "sprężyna|lato|jesień|zima", + "constellations": "baran|byk|bliźnięta|rak|lew|dziewica|waga|skorpion|strzelec|koziorożec|wodnik|ryby", + "year": "1 rok|2 lata|%d lat", + "month": "1 miesiąc|2 miesiące|%d miesięcy", + "week": "1 tydzień|2 tygodnie|%d tygodni", + "day": "1 dzień|%d dni", + "hour": "1 godzina|2 godziny|%d godzin", + "minute": "1 minuta|2 minuty|%d minut", + "second": "1 sekunda|2 sekundy|%d sekund", + "now": "teraz", + "ago": "%s temu", + "from_now": "%s po", + "before": "%s przed", + "after": "%s po" +} \ No newline at end of file diff --git a/lang/pt.json b/lang/pt.json index 92a8ecdc..1602eead 100755 --- a/lang/pt.json +++ b/lang/pt.json @@ -1,4 +1,5 @@ { + "name": "Portuguese", "months": "Janeiro|Fevereiro|Março|Abril|Maio|Junho|Julho|Agosto|Setembro|Outubro|Novembro|Dezembro", "short_months": "Jan|Fev|Mar|Abr|Maio|Jun|Jul|Ago|Set|Out|Nov|Dez", "weeks": "Domingo|Segunda-feira|Terça-feira|Quarta-feira|Quinta-feira|Sexta-feira|Sábado", diff --git a/lang/ro.json b/lang/ro.json index d64977e3..a11bc4b6 100644 --- a/lang/ro.json +++ b/lang/ro.json @@ -1,4 +1,5 @@ { + "name": "Romanian", "months": "Ianuarie|Februarie|Martie|Aprilie|Mai|Iunie|Iulie|August|Septembrie|Octombrie|Noiembrie|Decembrie", "short_months": "Ian|Feb|Mar|Apr|Mai|Iun|Iul|Aug|Sep|Oct|Noi|Dec", "weeks": "Duminică|Luni|Marți|Miercuri|Joi|Vineri|Sîmbătă", diff --git a/lang/ru.json b/lang/ru.json index de5771a5..74439744 100755 --- a/lang/ru.json +++ b/lang/ru.json @@ -1,4 +1,5 @@ { + "name": "Russian", "months": "Январь|Февраль|Март|Апрель|Май|Июнь|Июль|Август|Сентябрь|Октябрь|Ноябрь|Декабрь", "short_months": "Янв|Фев|Мар|Апр|Май|Июн|Июл|Авг|Сен|Окт|Ноя|Дек", "weeks": "Воскресенье|Понедельник|Вторник|Среда|Четверг|Пятница|Суббота", diff --git a/lang/se.json b/lang/se.json index ffd73015..5b210026 100644 --- a/lang/se.json +++ b/lang/se.json @@ -1,4 +1,5 @@ { + "name": "Swedish", "months": "Januari|Februari|Mars|April|Maj|Juni|Juli|Augusti|September|Oktober|November|December", "short_months": "Jan|Feb|Mars|April|Maj|Juni|Juli|Aug|Sep|Okt|Nov|Dec", "weeks": "Söndag|Måndag|Tisdag|Onsdag|Torsdag|Fredag|Lördag", diff --git a/lang/th.json b/lang/th.json index 81d3709c..4ca378f4 100755 --- a/lang/th.json +++ b/lang/th.json @@ -1,4 +1,5 @@ { + "name": "Thailand", "months": "มกราคม|กุมภาพันธ์|มีนาคม|เมษายน|พฤษภาคม|มิถุนายน|กรกฎาคม|สิงหาคม|กันยายน|ตุลาคม|พฤศจิกายน|ธันวาคม", "short_months": "ม.ค.|ก.พ.|มี.ค.|เม.ย.|พ.ค.|มิ.ย.|ก.ค.|ส.ค.|ก.ย.|ต.ค.|พ.ย.|ธ.ค.", "weeks": "อาทิตย์|จันทร์|อังคาร|พุธ|พฤหัสบดี|ศุกร์|เสาร์", diff --git a/lang/tr.json b/lang/tr.json index 0e7f9af9..c2bcddc8 100644 --- a/lang/tr.json +++ b/lang/tr.json @@ -1,4 +1,5 @@ { + "name": "Turkish", "months": "Ocak|Şubat|Mart|Nisan|Mayıs|Haziran|Temmuz|Ağustos|Eylül|Ekim|Kasım|Aralık", "short_months": "Oca|Şub|Mar|Nis|May|Haz|Tem|Ağu|Eyl|Eki|Kas|Ara", "weeks": "Pazar|Pazartesi|Salı|Çarşamba|Perşembe|Cuma|Cumartesi", diff --git a/lang/uk.json b/lang/uk.json index 9b551c3c..e9791585 100644 --- a/lang/uk.json +++ b/lang/uk.json @@ -1,4 +1,5 @@ { + "name": "Ukrainian", "months": "січня|лютого|березня|квітня|травня|червня|липня|серпня|вересня|жовтня|листопада|грудня", "short_months": "січ|лют|бер|квіт|трав|черв|лип|серп|вер|жовт|лист|груд", "weeks": "неділя|понеділок|вівторок|середа|четвер|п’ятниця|субота", diff --git a/lang/vi.json b/lang/vi.json index c8a1b3b0..87a8ee9c 100644 --- a/lang/vi.json +++ b/lang/vi.json @@ -1,4 +1,5 @@ { + "name": "VietNamese", "months": "Tháng Một|Tháng Hai|Tháng Ba|Tháng Tư|Tháng Năm|Tháng Sáu|Tháng Bảy|Tháng Tám|Tháng Chín|Tháng Mười|Tháng Mười Một|Tháng Mười Hai", "short_months": "Giêng|Hai|Ba|Bốn|Năm|Sáu|Bảy|Tám|Chìn|Mười|Một|Chạp", "weeks": "Chủ Nhật|Thứ Hai|Thứ Ba|Thứ Tư|Thứ Năm|Thứ Sáu|Thứ Bảy", diff --git a/lang/zh-CN.json b/lang/zh-CN.json index 283c5893..89036c56 100755 --- a/lang/zh-CN.json +++ b/lang/zh-CN.json @@ -1,4 +1,5 @@ { + "name": "Simplified Chinese", "months": "一月|二月|三月|四月|五月|六月|七月|八月|九月|十月|十一月|十二月", "short_months": "1月|2月|3月|4月|5月|6月|7月|8月|9月|10月|11月|12月", "weeks": "星期日|星期一|星期二|星期三|星期四|星期五|星期六", diff --git a/lang/zh-TW.json b/lang/zh-TW.json index 87941cb8..6e9c1f2c 100755 --- a/lang/zh-TW.json +++ b/lang/zh-TW.json @@ -1,4 +1,5 @@ { + "name": "Traditional Chinese", "months": "一月|二月|三月|四月|五月|六月|七月|八月|九月|十月|十一月|十二月", "short_months": "1月|2月|3月|4月|5月|6月|7月|8月|9月|10月|11月|12月", "weeks": "星期日|星期一|星期二|星期三|星期四|星期五|星期六",