|
| 1 | +package kurdical |
| 2 | + |
| 3 | +// julianDayNumber calculates the Julian Day Number for a Gregorian date. |
| 4 | +func julianDayNumber(year, month, day int) int { |
| 5 | + a := (14 - month) / 12 |
| 6 | + y := year + 4800 - a |
| 7 | + m := month + 12*a - 3 |
| 8 | + return day + (153*m+2)/5 + 365*y + y/4 - y/100 + y/400 - 32045 |
| 9 | +} |
| 10 | + |
| 11 | +// jdnToGregorian converts Julian Day Number to Gregorian date. |
| 12 | +func jdnToGregorian(jdn int) (year, month, day int) { |
| 13 | + l := jdn + 68569 |
| 14 | + n := (4 * l) / 146097 |
| 15 | + l = l - (146097*n+3)/4 |
| 16 | + i := (4000 * (l + 1)) / 1461001 |
| 17 | + l = l - (1461*i)/4 + 31 |
| 18 | + j := (80 * l) / 2447 |
| 19 | + day = l - (2447*j)/80 |
| 20 | + l = j / 11 |
| 21 | + month = j + 2 - 12*l |
| 22 | + year = 100*(n-49) + i + l |
| 23 | + return |
| 24 | +} |
| 25 | + |
| 26 | +// isSolarHijriLeap determines if a Solar Hijri year is leap. |
| 27 | +func isSolarHijriLeap(year int) bool { |
| 28 | + return (year+1)%4 == 0 |
| 29 | +} |
| 30 | + |
| 31 | +// gregorianToSolarHijri converts Gregorian date to Solar Hijri. |
| 32 | +func gregorianToSolarHijri(gYear, gMonth, gDay int) (sYear, sMonth, sDay int) { |
| 33 | + gJDN := julianDayNumber(gYear, gMonth, gDay) |
| 34 | + sJDN := gJDN - 1948087 |
| 35 | + sYear = 1 |
| 36 | + for { |
| 37 | + daysInYear := 365 |
| 38 | + if isSolarHijriLeap(sYear) { |
| 39 | + daysInYear = 366 |
| 40 | + } |
| 41 | + if sJDN <= daysInYear { |
| 42 | + break |
| 43 | + } |
| 44 | + sJDN -= daysInYear |
| 45 | + sYear++ |
| 46 | + } |
| 47 | + monthDays := []int{31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29} |
| 48 | + if isSolarHijriLeap(sYear) { |
| 49 | + monthDays[11] = 30 |
| 50 | + } |
| 51 | + sMonth = 1 |
| 52 | + for sMonth <= 12 { |
| 53 | + if sJDN <= monthDays[sMonth-1] { |
| 54 | + sDay = sJDN |
| 55 | + break |
| 56 | + } |
| 57 | + sJDN -= monthDays[sMonth-1] |
| 58 | + sMonth++ |
| 59 | + } |
| 60 | + return |
| 61 | +} |
| 62 | + |
| 63 | +// solarHijriToGregorian converts Solar Hijri date to Gregorian. |
| 64 | +func solarHijriToGregorian(sYear, sMonth, sDay int) (gYear, gMonth, gDay int) { |
| 65 | + days := 0 |
| 66 | + for y := 1; y < sYear; y++ { |
| 67 | + days += 365 |
| 68 | + if isSolarHijriLeap(y) { |
| 69 | + days++ |
| 70 | + } |
| 71 | + } |
| 72 | + monthDays := []int{31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29} |
| 73 | + if isSolarHijriLeap(sYear) { |
| 74 | + monthDays[11] = 30 |
| 75 | + } |
| 76 | + for m := 1; m < sMonth; m++ { |
| 77 | + days += monthDays[m-1] |
| 78 | + } |
| 79 | + days += sDay - 1 |
| 80 | + jdn := 1948087 + days |
| 81 | + gYear, gMonth, gDay = jdnToGregorian(jdn) |
| 82 | + return |
| 83 | +} |
0 commit comments