@@ -17,30 +17,23 @@ import {AnyCalendarDate, Calendar} from '../types';
17
17
import { CalendarDate } from '../CalendarDate' ;
18
18
import { mod } from '../utils' ;
19
19
20
- const PERSIAN_EPOCH = 1948321 ; // 622/03/19 Julian C.E.
21
-
22
- function isLeapYear ( year : number ) : boolean {
23
- let y0 = year > 0 ? year - 474 : year - 473 ;
24
- let y1 = mod ( y0 , 2820 ) + 474 ;
25
-
26
- return mod ( ( y1 + 38 ) * 31 , 128 ) < 31 ;
27
- }
28
-
29
- function persianToJulianDay ( year : number , month : number , day : number ) : number {
30
- let y0 = year > 0 ? year - 474 : year - 473 ;
31
- let y1 = mod ( y0 , 2820 ) + 474 ;
32
- let offset = month <= 7 ? 31 * ( month - 1 ) : 30 * ( month - 1 ) + 6 ;
33
-
34
- return (
35
- PERSIAN_EPOCH -
36
- 1 +
37
- 1029983 * Math . floor ( y0 / 2820 ) +
38
- 365 * ( y1 - 1 ) +
39
- Math . floor ( ( 31 * y1 - 5 ) / 128 ) +
40
- offset +
41
- day
42
- ) ;
43
- }
20
+ const PERSIAN_EPOCH = 1948320 ;
21
+
22
+ // Number of days from the start of the year to the start of each month.
23
+ const MONTH_START = [
24
+ 0 , // Farvardin
25
+ 31 , // Ordibehesht
26
+ 62 , // Khordad
27
+ 93 , // Tir
28
+ 124 , // Mordad
29
+ 155 , // Shahrivar
30
+ 186 , // Mehr
31
+ 216 , // Aban
32
+ 246 , // Azar
33
+ 276 , // Dey
34
+ 306 , // Bahman
35
+ 336 // Esfand
36
+ ] ;
44
37
45
38
/**
46
39
* The Persian calendar is the main calendar used in Iran and Afghanistan. It has 12 months
@@ -52,24 +45,22 @@ export class PersianCalendar implements Calendar {
52
45
identifier = 'persian' ;
53
46
54
47
fromJulianDay ( jd : number ) : CalendarDate {
55
- let d0 = jd - persianToJulianDay ( 475 , 1 , 1 ) ;
56
- let n2820 = Math . floor ( d0 / 1029983 ) ;
57
- let d1 = mod ( d0 , 1029983 ) ;
58
- let y2820 = d1 === 1029982 ? 2820 : Math . floor ( ( 128 * d1 + 46878 ) / 46751 ) ;
59
- let year = 474 + 2820 * n2820 + y2820 ;
60
- if ( year <= 0 ) {
61
- year -- ;
62
- }
63
-
64
- let yDay = jd - persianToJulianDay ( year , 1 , 1 ) + 1 ;
65
- let month = yDay <= 186 ? Math . ceil ( yDay / 31 ) : Math . ceil ( ( yDay - 6 ) / 31 ) ;
66
- let day = jd - persianToJulianDay ( year , month , 1 ) + 1 ;
67
-
68
- return new CalendarDate ( this , year , month , day ) ;
48
+ let daysSinceEpoch = jd - PERSIAN_EPOCH ;
49
+ let year = 1 + Math . floor ( ( 33 * daysSinceEpoch + 3 ) / 12053 ) ;
50
+ let farvardin1 = 365 * ( year - 1 ) + Math . floor ( ( 8 * year + 21 ) / 33 ) ;
51
+ let dayOfYear = daysSinceEpoch - farvardin1 ;
52
+ let month = dayOfYear < 216
53
+ ? Math . floor ( dayOfYear / 31 )
54
+ : Math . floor ( ( dayOfYear - 6 ) / 30 ) ;
55
+ let day = dayOfYear - MONTH_START [ month ] + 1 ;
56
+ return new CalendarDate ( this , year , month + 1 , day ) ;
69
57
}
70
58
71
59
toJulianDay ( date : AnyCalendarDate ) : number {
72
- return persianToJulianDay ( date . year , date . month , date . day ) ;
60
+ let jd = PERSIAN_EPOCH - 1 + 365 * ( date . year - 1 ) + Math . floor ( ( 8 * date . year + 21 ) / 33 ) ;
61
+ jd += MONTH_START [ date . month - 1 ] ;
62
+ jd += date . day ;
63
+ return jd ;
73
64
}
74
65
75
66
getMonthsInYear ( ) : number {
@@ -85,7 +76,8 @@ export class PersianCalendar implements Calendar {
85
76
return 30 ;
86
77
}
87
78
88
- return isLeapYear ( date . year ) ? 30 : 29 ;
79
+ let isLeapYear = mod ( 25 * date . year + 11 , 33 ) < 8 ;
80
+ return isLeapYear ? 30 : 29 ;
89
81
}
90
82
91
83
getEras ( ) {
0 commit comments