init
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
package jalali
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
var MonthNames = [...]string{
|
||||
"", "Farvardin", "Ordibehesht", "Khordad", "Tir", "Mordad", "Shahrivar",
|
||||
"Mehr", "Aban", "Azar", "Dey", "Bahman", "Esfand",
|
||||
}
|
||||
|
||||
var MonthNamesFA = [...]string{
|
||||
"", "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور",
|
||||
"مهر", "آبان", "آذر", "دی", "بهمن", "اسفند",
|
||||
}
|
||||
|
||||
type Date struct {
|
||||
Year int
|
||||
Month int
|
||||
Day int
|
||||
}
|
||||
|
||||
func (d Date) String() string { return fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day) }
|
||||
|
||||
func IsLeap(year int) bool {
|
||||
return ToGregorian(year+1, 1, 1).Sub(ToGregorian(year, 1, 1)) == 366*24*time.Hour
|
||||
}
|
||||
|
||||
func DaysInMonth(year, month int) int {
|
||||
if month <= 6 {
|
||||
return 31
|
||||
}
|
||||
if month <= 11 {
|
||||
return 30
|
||||
}
|
||||
if IsLeap(year) {
|
||||
return 30
|
||||
}
|
||||
return 29
|
||||
}
|
||||
|
||||
func FromTime(t time.Time) Date {
|
||||
gy, gm, gd := t.Date()
|
||||
jy, jm, jd := gregorianToJalali(gy, int(gm), gd)
|
||||
return Date{jy, jm, jd}
|
||||
}
|
||||
|
||||
func ToGregorian(jy, jm, jd int) time.Time {
|
||||
gy, gm, gd := jalaliToGregorian(jy, jm, jd)
|
||||
return time.Date(gy, time.Month(gm), gd, 0, 0, 0, 0, time.Local)
|
||||
}
|
||||
|
||||
func gregorianToJalali(gy, gm, gd int) (int, int, int) {
|
||||
gdm := [...]int{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}
|
||||
gy2 := gy
|
||||
if gm > 2 {
|
||||
gy2++
|
||||
}
|
||||
days := 355666 + 365*gy + (gy2+3)/4 - (gy2+99)/100 + (gy2+399)/400 + gd + gdm[gm-1]
|
||||
jy := -1595 + 33*(days/12053)
|
||||
days %= 12053
|
||||
jy += 4 * (days / 1461)
|
||||
days %= 1461
|
||||
if days > 365 {
|
||||
jy += (days - 1) / 365
|
||||
days = (days - 1) % 365
|
||||
}
|
||||
if days < 186 {
|
||||
return jy, 1 + days/31, 1 + days%31
|
||||
}
|
||||
return jy, 7 + (days-186)/30, 1 + (days-186)%30
|
||||
}
|
||||
|
||||
func jalaliToGregorian(jy, jm, jd int) (int, int, int) {
|
||||
jy += 1595
|
||||
days := -355668 + 365*jy + (jy/33)*8 + (jy%33+3)/4 + jd
|
||||
if jm < 7 {
|
||||
days += (jm - 1) * 31
|
||||
} else {
|
||||
days += (jm-7)*30 + 186
|
||||
}
|
||||
gy := 400 * (days / 146097)
|
||||
days %= 146097
|
||||
if days > 36524 {
|
||||
gy += 100 * ((days - 1) / 36524)
|
||||
days = (days - 1) % 36524
|
||||
if days >= 365 {
|
||||
days++
|
||||
}
|
||||
}
|
||||
gy += 4 * (days / 1461)
|
||||
days %= 1461
|
||||
if days > 365 {
|
||||
gy += (days - 1) / 365
|
||||
days = (days - 1) % 365
|
||||
}
|
||||
gd := days + 1
|
||||
sal := [...]int{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||
if (gy%4 == 0 && gy%100 != 0) || gy%400 == 0 {
|
||||
sal[2] = 29
|
||||
}
|
||||
gm := 1
|
||||
for gm <= 12 && gd > sal[gm] {
|
||||
gd -= sal[gm]
|
||||
gm++
|
||||
}
|
||||
return gy, gm, gd
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package jalali
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestKnownDates(t *testing.T) {
|
||||
tests := []struct {
|
||||
gregorian string
|
||||
jalali Date
|
||||
}{
|
||||
{"2024-03-20", Date{1403, 1, 1}},
|
||||
{"2025-03-21", Date{1404, 1, 1}},
|
||||
{"2026-07-28", Date{1405, 5, 6}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
g, _ := time.Parse("2006-01-02", tt.gregorian)
|
||||
if got := FromTime(g); got != tt.jalali {
|
||||
t.Errorf("%s: got %v, want %v", tt.gregorian, got, tt.jalali)
|
||||
}
|
||||
back := ToGregorian(tt.jalali.Year, tt.jalali.Month, tt.jalali.Day)
|
||||
if got := back.Format("2006-01-02"); got != tt.gregorian {
|
||||
t.Errorf("%v: got %s, want %s", tt.jalali, got, tt.gregorian)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthLength(t *testing.T) {
|
||||
if got := DaysInMonth(1399, 12); got != 30 {
|
||||
t.Fatalf("leap Esfand: got %d, want 30", got)
|
||||
}
|
||||
if got := DaysInMonth(1400, 12); got != 29 {
|
||||
t.Fatalf("regular Esfand: got %d, want 29", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user