1- part of persian;
2-
3- int _getJulianDayNumber (int year, int month, int day) {
4- return (((year + ((month - 8 ) ~ / 6 ) + 100100 ) * 1461 ) ~ / 4 ) +
5- ((153 * ((month + 9 ) % 12 ) + 2 ) ~ / 5 ) +
6- day -
7- 34840408 -
8- ((((year + 100100 + ((month - 8 ) ~ / 6 )) ~ / 100 ) * 3 ) ~ / 4 ) +
9- 752 ;
10- }
1+ part of '../persian.dart' ;
112
123/// An instant in Persian calendar, such as Farvardin 11, 1365.
134class PersianDate {
145 /// Creates a [PersianDate] from the Persian year, month and day.
156 ///
167 /// Example: PersianDate(1400, 12, 29);
17- const PersianDate (
18- this .year,
19- this .month,
20- this .day,
21- );
8+ const PersianDate (this .year, this .month, this .day);
229
2310 /// Creates a [PersianDate] from the equivalent [DateTime] .
2411 factory PersianDate .fromDateTime (DateTime date) {
25- final julianDayNumber =
26- _getJulianDayNumber (date.year, date.month, date.day);
27- final int year = date.year;
28- int persianYear = year - 621 ;
29- final r = _PersianDateCalculation .calculate (persianYear);
30- final int jdn1f = _getJulianDayNumber (year, 3 , r.march);
31- int k = julianDayNumber - jdn1f;
32- // Find number of days that passed since 1 Farvardin.
33- if (k >= 0 ) {
34- if (k <= 185 ) {
35- // The first 6 months.
36- final int jm = 1 + (k ~ / 31 );
37- final int jd = (k % 31 ) + 1 ;
38-
39- return PersianDate (persianYear, jm, jd);
40- } else {
41- // The remaining months.
42- k -= 186 ;
43- }
44- } else {
45- // Previous Persian year.
46- persianYear -= 1 ;
47- k += 179 ;
48- if (r.leap == 1 ) k += 1 ;
49- }
50- final int jm = 7 + (k ~ / 30 );
51- final int jd = (k % 30 ) + 1 ;
52-
53- return PersianDate (persianYear, jm, jd);
12+ return toPersian (date.year, date.month, date.day);
5413 }
5514
5615 /// Constructs a new [PersianDate] instance
@@ -67,10 +26,8 @@ class PersianDate {
6726 bool isUtc = false ,
6827 }) =>
6928 PersianDate .fromDateTime (
70- DateTime .fromMillisecondsSinceEpoch (
71- millisecondsSinceEpoch,
72- isUtc: isUtc,
73- ),
29+ DateTime .fromMillisecondsSinceEpoch (millisecondsSinceEpoch,
30+ isUtc: isUtc),
7431 );
7532
7633 /// Constructs a new [PersianDate] instance
@@ -86,10 +43,8 @@ class PersianDate {
8643 bool isUtc = false ,
8744 }) =>
8845 PersianDate .fromDateTime (
89- DateTime .fromMicrosecondsSinceEpoch (
90- microsecondsSinceEpoch,
91- isUtc: isUtc,
92- ),
46+ DateTime .fromMicrosecondsSinceEpoch (microsecondsSinceEpoch,
47+ isUtc: isUtc),
9348 );
9449
9550 /// The Year.
@@ -101,109 +56,54 @@ class PersianDate {
10156 /// The Day.
10257 final int day;
10358
104- @override
105- String toString () {
106- return '$year /${month .toString ().padLeft (2 , '0' )}/${day .toString ().padLeft (2 , '0' )}'
107- .withPersianNumbers ();
59+ /// Converts this [PersianDate] instance to a [DateTime] .
60+ DateTime toDateTime () {
61+ return toGregorian (year, month, day);
10862 }
109- }
110-
111- /// Internal class
112- class _PersianDateCalculation {
113- const _PersianDateCalculation ({
114- required this .leap,
115- required this .gy,
116- required this .march,
117- });
118-
119- /// This determines if the Persian Year is
120- /// leap (366-day long) or is the common year (365 days), and
121- /// finds the day in March (Gregorian calendar) of the first
122- /// day of the Persian Year.
123- ///
124- /// [1. see here] (http://www.astro.uni.torun.pl/~kb/Papers/EMP/PersianC-EMP.htm)
125- ///
126- /// [2. see here] (http://www.fourmilab.ch/documents/calendar/)
127- factory _PersianDateCalculation .calculate (int persianYear) {
128- // Persian years starting the 33-year rule.
12963
130- final int bl = breaks.length;
131- final int gy = persianYear + 621 ;
132- int leapJ = - 14 ;
133- int jp = breaks[0 ];
134- int jump = 0 ;
64+ /// Checks whether a Persian date is valid or not.
65+ static bool isValidPersianDate (
66+ int persianYear, int persianMonth, int persianDay) {
67+ return persianYear >= - 61 &&
68+ persianYear <= 3177 &&
69+ persianMonth >= 1 &&
70+ persianMonth <= 12 &&
71+ persianDay >= 1 &&
72+ persianDay <= getDaysInPersianMonth (persianYear, persianMonth);
73+ }
13574
136- // should not happen
137- if (persianYear < - 61 || persianYear >= 3178 ) {
138- throw StateError ('should not happen' );
75+ /// Get the number of days in a Persian year.
76+ static int getDaysInPersianYear (int persianYear) {
77+ if (isLeapPersianYear (persianYear)) {
78+ return 366 ;
13979 }
14080
141- // Find the limiting years for the Persian year jy.
142- for (int i = 1 ; i < bl; i += 1 ) {
143- final int jm = breaks[i];
144- jump = jm - jp;
145- if (persianYear < jm) {
146- break ;
147- }
148- leapJ = leapJ + (jump ~ / 33 ) * 8 + (((jump % 33 )) ~ / 4 );
149- jp = jm;
150- }
151- int n = persianYear - jp;
81+ return 365 ;
82+ }
15283
153- // Find the number of leap years from AD 621 to the beginning
154- // of the current Persian year in the Persian calendar.
155- leapJ = leapJ + ((n) ~ / 33 ) * 8 + (((n % 33 ) + 3 ) ~ / 4 );
156- if ((jump % 33 ) == 4 && jump - n == 4 ) {
157- leapJ += 1 ;
84+ /// Number of days in a given month in a Persian year.
85+ static int getDaysInPersianMonth (int persianYear, int persianMonth) {
86+ if (persianMonth < 7 ) {
87+ return 31 ;
15888 }
159-
160- // And the same in the Gregorian calendar (until the year gy).
161- final int leapG = ((gy) ~ / 4 ) - (((((gy) ~ / 100 ) + 1 ) * 3 ) ~ / 4 ) - 150 ;
162-
163- // Determine the Gregorian date of Farvardin the 1st.
164- final int march = 20 + leapJ - leapG;
165-
166- // Find how many years have passed since the last leap year.
167- if (jump - n < 6 ) {
168- n = n - jump + ((jump + 4 ) ~ / 33 ) * 33 ;
89+ if (persianMonth < 12 ) {
90+ return 30 ;
16991 }
170- int leap = ((((n + 1 ) % 33 ) - 1 ) % 4 );
171- if (leap == - 1 ) {
172- leap = 4 ;
92+ if (isLeapPersianYear (persianYear)) {
93+ return 30 ;
17394 }
17495
175- return _PersianDateCalculation (leap : leap, gy : gy, march : march) ;
96+ return 29 ;
17697 }
17798
178- /// Number of years since the last leap year (0 to 4)
179- final int leap;
180-
181- /// Gregorian year of the beginning of Persian year
182- final int gy;
183-
184- /// The March day of Farvardin the 1st (1st day of jy)
185- final int march;
99+ /// Is this a leap year or not?
100+ static bool isLeapPersianYear (int persianYear) {
101+ return persianCalendar (persianYear)! .leap == 0 ;
102+ }
186103
187- static final List <int > breaks = const [
188- - 61 ,
189- 9 ,
190- 38 ,
191- 199 ,
192- 426 ,
193- 686 ,
194- 756 ,
195- 818 ,
196- 1111 ,
197- 1181 ,
198- 1210 ,
199- 1635 ,
200- 2060 ,
201- 2097 ,
202- 2192 ,
203- 2262 ,
204- 2324 ,
205- 2394 ,
206- 2456 ,
207- 3178 ,
208- ];
104+ @override
105+ String toString () {
106+ return '$year /${month .toString ().padLeft (2 , '0' )}/${day .toString ().padLeft (2 , '0' )}'
107+ .withPersianNumbers ();
108+ }
209109}
0 commit comments