|
| 1 | +package jalaali |
| 2 | + |
| 3 | +import "time" |
| 4 | + |
| 5 | +var ( |
| 6 | +breaks = [...]int{-61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210, |
| 7 | +1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178} |
| 8 | +) |
| 9 | + |
| 10 | +// ToJalaali converts Gregorian to Jalaali date. Error is not nil if Jalaali |
| 11 | +// year passed to function is not valid. |
| 12 | +func ToJalaali(gregorianYear int, gregorianMonth time.Month, gregorianDay int) (int, Month, int, error) { |
| 13 | +jy, jm, jd, err := d2j(g2d(gregorianYear, int(gregorianMonth), gregorianDay)) |
| 14 | +return jy, Month(jm), jd, err |
| 15 | +} |
| 16 | + |
| 17 | +// ToGregorian converts Jalaali to Gregorian date. Error is not nil if Jalaali |
| 18 | +// year passed to function is not valid. |
| 19 | +func ToGregorian(jalaaliYear int, jalaaliMonth Month, jalaaliDay int) (int, time.Month, int, error) { |
| 20 | +jdn, err := j2d(jalaaliYear, int(jalaaliMonth), jalaaliDay) |
| 21 | +if err != nil { |
| 22 | +return 0, 0, 0, err |
| 23 | +} |
| 24 | + |
| 25 | +gy, gm, gd := d2g(jdn) |
| 26 | +return gy + 1400, time.Month(gm), gd, nil |
| 27 | +} |
| 28 | + |
| 29 | +func j2d(jy, jm, jd int) (jdn int, err error) { |
| 30 | +_, gy, march, err := jalCal(jy) |
| 31 | +if err != nil { |
| 32 | +return 0, err |
| 33 | +} |
| 34 | +return g2d(gy, 3, march) + (jm-1)*31 - div(jm, 7)*(jm-7) + jd - 1, nil |
| 35 | +} |
| 36 | + |
| 37 | +func d2j(jdn int) (int, int, int, error) { |
| 38 | +gy, _, _ := d2g(jdn) // Calculate Gregorian year (gy). |
| 39 | +jy := gy - 621 |
| 40 | +leap, _, march, err := jalCal(jy) |
| 41 | +jdn1f := g2d(gy, 3, march) |
| 42 | + |
| 43 | +if err != nil { |
| 44 | +return 0, 0, 0, err |
| 45 | +} |
| 46 | + |
| 47 | +// Find number of days that passed since 1 Farvardin. |
| 48 | +k := jdn - jdn1f |
| 49 | +if k >= 0 { |
| 50 | +if k <= 185 { |
| 51 | +// The first 6 months. |
| 52 | +jm := 1 + div(k, 31) |
| 53 | +jd := mod(k, 31) + 1 |
| 54 | +return jy, jm, jd, nil |
| 55 | +} |
| 56 | +// The remaining months. |
| 57 | +k -= 186 |
| 58 | +} else { |
| 59 | +// Previous Jalaali year. |
| 60 | +jy-- |
| 61 | +k += 179 |
| 62 | +if leap == 1 { |
| 63 | +k++ |
| 64 | +} |
| 65 | +} |
| 66 | +jm := 7 + div(k, 30) |
| 67 | +jd := mod(k, 30) + 1 |
| 68 | +return jy, jm, jd, nil |
| 69 | +} |
| 70 | + |
| 71 | +func jalCal(jy int) (int, int, int, error) { |
| 72 | +bl, gy, leapJ, jp := len(breaks), jy+621, -14, breaks[0] |
| 73 | +jump := 0 |
| 74 | + |
| 75 | +if jy < jp || jy >= breaks[bl-1] { |
| 76 | +return 0, 0, 0, &ErrorInvalidYear{jy} |
| 77 | +} |
| 78 | + |
| 79 | +// Find the limiting years for the Jalaali year jy. |
| 80 | +for i := 1; i < bl; i++ { |
| 81 | +jm := breaks[i] |
| 82 | +jump = jm - jp |
| 83 | +if jy < jm { |
| 84 | +break |
| 85 | +} |
| 86 | +leapJ += div(jump, 33)*8 + div(mod(jump, 33), 4) |
| 87 | +jp = jm |
| 88 | +} |
| 89 | +n := jy - jp |
| 90 | + |
| 91 | +// Find the number of leap years from AD 621 to the beginning |
| 92 | +// of the current Jalaali year in the Persian calendar. |
| 93 | +leapJ += div(n, 33)*8 + div(mod(n, 33)+3, 4) |
| 94 | +if mod(jump, 33) == 4 && jump-n == 4 { |
| 95 | +leapJ++ |
| 96 | +} |
| 97 | + |
| 98 | +// And the same in the Gregorian calendar (until the year gy). |
| 99 | +leapG := div(gy, 4) - div((div(gy, 100)+1)*3, 4) - 150 |
| 100 | + |
| 101 | +// Determine the Gregorian date of Farvardin the 1st. |
| 102 | +march := 20 + leapJ - leapG |
| 103 | + |
| 104 | +// Find how many years have passed since the last leap year. |
| 105 | +if jump-n < 6 { |
| 106 | +n -= jump + div(jump+4, 33)*33 |
| 107 | +} |
| 108 | +leap := mod(mod(n+1, 33)-1, 4) |
| 109 | +if leap == -1 { |
| 110 | +leap = 4 |
| 111 | +} |
| 112 | + |
| 113 | +return leap, gy, march, nil |
| 114 | +} |
| 115 | + |
| 116 | +func g2d(gy, gm, gd int) int { |
| 117 | +d := div((gy+div(gm-8, 6)+100100)*1461, 4) + |
| 118 | +div(153*mod(gm+9, 12)+2, 5) + |
| 119 | +gd - 34840408 |
| 120 | +d = d - div(div(gy+100100+div(gm-8, 6), 100)*3, 4) + 752 |
| 121 | +return d |
| 122 | +} |
| 123 | + |
| 124 | +func d2g(jdn int) (int, int, int) { |
| 125 | +j := 4*jdn + 139361631 |
| 126 | +j = j + div(div(4*jdn+183187720, 146097)*3, 4)*4 - 3908 |
| 127 | +i := div(mod(j, 1461), 4)*5 + 308 |
| 128 | +gd := div(mod(i, 153), 5) + 1 |
| 129 | +gm := mod(div(i, 153), 12) + 1 |
| 130 | +gy := div(j, 1461) - 100100 + div(8-gm, 6) |
| 131 | +return gy, gm, gd |
| 132 | +} |
| 133 | + |
| 134 | +func div(a, b int) int { |
| 135 | +return a / b |
| 136 | +} |
| 137 | + |
| 138 | +func mod(a, b int) int { |
| 139 | +return a % b |
| 140 | +} |
0 commit comments