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 }