Files
team-presence/internal/jalali/jalali.go
T
2026-07-28 02:04:36 +03:30

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
}