110 lines
2.3 KiB
Go
110 lines
2.3 KiB
Go
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
|
|
}
|