Fix StyleCop warning SA1005 (single line comment spacing)
[mono-project.git] / netcore / System.Private.CoreLib / shared / System / Globalization / UmAlQuraCalendar.cs
blobae5820841e48c6d88f10ba7953ee24b6834ab47a
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Diagnostics;
7 namespace System.Globalization
9 /// <remarks>
10 /// Calendar support range:
11 /// Calendar Minimum Maximum
12 /// ========== ========== ==========
13 /// Gregorian 1900/04/30 2077/05/13
14 /// UmAlQura 1318/01/01 1500/12/30
15 /// </remarks>
16 public partial class UmAlQuraCalendar : Calendar
18 private const int MinCalendarYear = 1318;
19 private const int MaxCalendarYear = 1500;
21 private struct DateMapping
23 internal DateMapping(int MonthsLengthFlags, int GYear, int GMonth, int GDay)
25 HijriMonthsLengthFlags = MonthsLengthFlags;
26 GregorianDate = new DateTime(GYear, GMonth, GDay);
29 internal int HijriMonthsLengthFlags;
30 internal DateTime GregorianDate;
33 private static readonly DateMapping[] s_hijriYearInfo = InitDateMapping();
35 private static DateMapping[] InitDateMapping()
37 short[] rawData = new short[]
39 // These data are taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync
40 /* DaysPerM GY GM GD D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12
41 1318*/0x02EA, 1900, 4, 30, /* 0 1 0 1 0 1 1 1 0 1 0 0 4/30/1900
42 1319*/0x06E9, 1901, 4, 19, /* 1 0 0 1 0 1 1 1 0 1 1 0 4/19/1901
43 1320*/0x0ED2, 1902, 4, 9, /* 0 1 0 0 1 0 1 1 0 1 1 1 4/9/1902
44 1321*/0x0EA4, 1903, 3, 30, /* 0 0 1 0 0 1 0 1 0 1 1 1 3/30/1903
45 1322*/0x0D4A, 1904, 3, 18, /* 0 1 0 1 0 0 1 0 1 0 1 1 3/18/1904
46 1323*/0x0A96, 1905, 3, 7, /* 0 1 1 0 1 0 0 1 0 1 0 1 3/7/1905
47 1324*/0x0536, 1906, 2, 24, /* 0 1 1 0 1 1 0 0 1 0 1 0 2/24/1906
48 1325*/0x0AB5, 1907, 2, 13, /* 1 0 1 0 1 1 0 1 0 1 0 1 2/13/1907
49 1326*/0x0DAA, 1908, 2, 3, /* 0 1 0 1 0 1 0 1 1 0 1 1 2/3/1908
50 1327*/0x0BA4, 1909, 1, 23, /* 0 0 1 0 0 1 0 1 1 1 0 1 1/23/1909
51 1328*/0x0B49, 1910, 1, 12, /* 1 0 0 1 0 0 1 0 1 1 0 1 1/12/1910
52 1329*/0x0A93, 1911, 1, 1, /* 1 1 0 0 1 0 0 1 0 1 0 1 1/1/1911
53 1330*/0x052B, 1911, 12, 21, /* 1 1 0 1 0 1 0 0 1 0 1 0 12/21/1911
54 1331*/0x0A57, 1912, 12, 9, /* 1 1 1 0 1 0 1 0 0 1 0 1 12/9/1912
55 1332*/0x04B6, 1913, 11, 29, /* 0 1 1 0 1 1 0 1 0 0 1 0 11/29/1913
56 1333*/0x0AB5, 1914, 11, 18, /* 1 0 1 0 1 1 0 1 0 1 0 1 11/18/1914
57 1334*/0x05AA, 1915, 11, 8, /* 0 1 0 1 0 1 0 1 1 0 1 0 11/8/1915
58 1335*/0x0D55, 1916, 10, 27, /* 1 0 1 0 1 0 1 0 1 0 1 1 10/27/1916
59 1336*/0x0D2A, 1917, 10, 17, /* 0 1 0 1 0 1 0 0 1 0 1 1 10/17/1917
60 1337*/0x0A56, 1918, 10, 6, /* 0 1 1 0 1 0 1 0 0 1 0 1 10/6/1918
61 1338*/0x04AE, 1919, 9, 25, /* 0 1 1 1 0 1 0 1 0 0 1 0 9/25/1919
62 1339*/0x095D, 1920, 9, 13, /* 1 0 1 1 1 0 1 0 1 0 0 1 9/13/1920
63 1340*/0x02EC, 1921, 9, 3, /* 0 0 1 1 0 1 1 1 0 1 0 0 9/3/1921
64 1341*/0x06D5, 1922, 8, 23, /* 1 0 1 0 1 0 1 1 0 1 1 0 8/23/1922
65 1342*/0x06AA, 1923, 8, 13, /* 0 1 0 1 0 1 0 1 0 1 1 0 8/13/1923
66 1343*/0x0555, 1924, 8, 1, /* 1 0 1 0 1 0 1 0 1 0 1 0 8/1/1924
67 1344*/0x04AB, 1925, 7, 21, /* 1 1 0 1 0 1 0 1 0 0 1 0 7/21/1925
68 1345*/0x095B, 1926, 7, 10, /* 1 1 0 1 1 0 1 0 1 0 0 1 7/10/1926
69 1346*/0x02BA, 1927, 6, 30, /* 0 1 0 1 1 1 0 1 0 1 0 0 6/30/1927
70 1347*/0x0575, 1928, 6, 18, /* 1 0 1 0 1 1 1 0 1 0 1 0 6/18/1928
71 1348*/0x0BB2, 1929, 6, 8, /* 0 1 0 0 1 1 0 1 1 1 0 1 6/8/1929
72 1349*/0x0764, 1930, 5, 29, /* 0 0 1 0 0 1 1 0 1 1 1 0 5/29/1930
73 1350*/0x0749, 1931, 5, 18, /* 1 0 0 1 0 0 1 0 1 1 1 0 5/18/1931
74 1351*/0x0655, 1932, 5, 6, /* 1 0 1 0 1 0 1 0 0 1 1 0 5/6/1932
75 1352*/0x02AB, 1933, 4, 25, /* 1 1 0 1 0 1 0 1 0 1 0 0 4/25/1933
76 1353*/0x055B, 1934, 4, 14, /* 1 1 0 1 1 0 1 0 1 0 1 0 4/14/1934
77 1354*/0x0ADA, 1935, 4, 4, /* 0 1 0 1 1 0 1 1 0 1 0 1 4/4/1935
78 1355*/0x06D4, 1936, 3, 24, /* 0 0 1 0 1 0 1 1 0 1 1 0 3/24/1936
79 1356*/0x0EC9, 1937, 3, 13, /* 1 0 0 1 0 0 1 1 0 1 1 1 3/13/1937
80 1357*/0x0D92, 1938, 3, 3, /* 0 1 0 0 1 0 0 1 1 0 1 1 3/3/1938
81 1358*/0x0D25, 1939, 2, 20, /* 1 0 1 0 0 1 0 0 1 0 1 1 2/20/1939
82 1359*/0x0A4D, 1940, 2, 9, /* 1 0 1 1 0 0 1 0 0 1 0 1 2/9/1940
83 1360*/0x02AD, 1941, 1, 28, /* 1 0 1 1 0 1 0 1 0 1 0 0 1/28/1941
84 1361*/0x056D, 1942, 1, 17, /* 1 0 1 1 0 1 1 0 1 0 1 0 1/17/1942
85 1362*/0x0B6A, 1943, 1, 7, /* 0 1 0 1 0 1 1 0 1 1 0 1 1/7/1943
86 1363*/0x0B52, 1943, 12, 28, /* 0 1 0 0 1 0 1 0 1 1 0 1 12/28/1943
87 1364*/0x0AA5, 1944, 12, 16, /* 1 0 1 0 0 1 0 1 0 1 0 1 12/16/1944
88 1365*/0x0A4B, 1945, 12, 5, /* 1 1 0 1 0 0 1 0 0 1 0 1 12/5/1945
89 1366*/0x0497, 1946, 11, 24, /* 1 1 1 0 1 0 0 1 0 0 1 0 11/24/1946
90 1367*/0x0937, 1947, 11, 13, /* 1 1 1 0 1 1 0 0 1 0 0 1 11/13/1947
91 1368*/0x02B6, 1948, 11, 2, /* 0 1 1 0 1 1 0 1 0 1 0 0 11/2/1948
92 1369*/0x0575, 1949, 10, 22, /* 1 0 1 0 1 1 1 0 1 0 1 0 10/22/1949
93 1370*/0x0D6A, 1950, 10, 12, /* 0 1 0 1 0 1 1 0 1 0 1 1 10/12/1950
94 1371*/0x0D52, 1951, 10, 2, /* 0 1 0 0 1 0 1 0 1 0 1 1 10/2/1951
95 1372*/0x0A96, 1952, 9, 20, /* 0 1 1 0 1 0 0 1 0 1 0 1 9/20/1952
96 1373*/0x092D, 1953, 9, 9, /* 1 0 1 1 0 1 0 0 1 0 0 1 9/9/1953
97 1374*/0x025D, 1954, 8, 29, /* 1 0 1 1 1 0 1 0 0 1 0 0 8/29/1954
98 1375*/0x04DD, 1955, 8, 18, /* 1 0 1 1 1 0 1 1 0 0 1 0 8/18/1955
99 1376*/0x0ADA, 1956, 8, 7, /* 0 1 0 1 1 0 1 1 0 1 0 1 8/7/1956
100 1377*/0x05D4, 1957, 7, 28, /* 0 0 1 0 1 0 1 1 1 0 1 0 7/28/1957
101 1378*/0x0DA9, 1958, 7, 17, /* 1 0 0 1 0 1 0 1 1 0 1 1 7/17/1958
102 1379*/0x0D52, 1959, 7, 7, /* 0 1 0 0 1 0 1 0 1 0 1 1 7/7/1959
103 1380*/0x0AAA, 1960, 6, 25, /* 0 1 0 1 0 1 0 1 0 1 0 1 6/25/1960
104 1381*/0x04D6, 1961, 6, 14, /* 0 1 1 0 1 0 1 1 0 0 1 0 6/14/1961
105 1382*/0x09B6, 1962, 6, 3, /* 0 1 1 0 1 1 0 1 1 0 0 1 6/3/1962
106 1383*/0x0374, 1963, 5, 24, /* 0 0 1 0 1 1 1 0 1 1 0 0 5/24/1963
107 1384*/0x0769, 1964, 5, 12, /* 1 0 0 1 0 1 1 0 1 1 1 0 5/12/1964
108 1385*/0x0752, 1965, 5, 2, /* 0 1 0 0 1 0 1 0 1 1 1 0 5/2/1965
109 1386*/0x06A5, 1966, 4, 21, /* 1 0 1 0 0 1 0 1 0 1 1 0 4/21/1966
110 1387*/0x054B, 1967, 4, 10, /* 1 1 0 1 0 0 1 0 1 0 1 0 4/10/1967
111 1388*/0x0AAB, 1968, 3, 29, /* 1 1 0 1 0 1 0 1 0 1 0 1 3/29/1968
112 1389*/0x055A, 1969, 3, 19, /* 0 1 0 1 1 0 1 0 1 0 1 0 3/19/1969
113 1390*/0x0AD5, 1970, 3, 8, /* 1 0 1 0 1 0 1 1 0 1 0 1 3/8/1970
114 1391*/0x0DD2, 1971, 2, 26, /* 0 1 0 0 1 0 1 1 1 0 1 1 2/26/1971
115 1392*/0x0DA4, 1972, 2, 16, /* 0 0 1 0 0 1 0 1 1 0 1 1 2/16/1972
116 1393*/0x0D49, 1973, 2, 4, /* 1 0 0 1 0 0 1 0 1 0 1 1 2/4/1973
117 1394*/0x0A95, 1974, 1, 24, /* 1 0 1 0 1 0 0 1 0 1 0 1 1/24/1974
118 1395*/0x052D, 1975, 1, 13, /* 1 0 1 1 0 1 0 0 1 0 1 0 1/13/1975
119 1396*/0x0A5D, 1976, 1, 2, /* 1 0 1 1 1 0 1 0 0 1 0 1 1/2/1976
120 1397*/0x055A, 1976, 12, 22, /* 0 1 0 1 1 0 1 0 1 0 1 0 12/22/1976
121 1398*/0x0AD5, 1977, 12, 11, /* 1 0 1 0 1 0 1 1 0 1 0 1 12/11/1977
122 1399*/0x06AA, 1978, 12, 1, /* 0 1 0 1 0 1 0 1 0 1 1 0 12/1/1978
123 1400*/0x0695, 1979, 11, 20, /* 1 0 1 0 1 0 0 1 0 1 1 0 11/20/1979
124 1401*/0x052B, 1980, 11, 8, /* 1 1 0 1 0 1 0 0 1 0 1 0 11/8/1980
125 1402*/0x0A57, 1981, 10, 28, /* 1 1 1 0 1 0 1 0 0 1 0 1 10/28/1981
126 1403*/0x04AE, 1982, 10, 18, /* 0 1 1 1 0 1 0 1 0 0 1 0 10/18/1982
127 1404*/0x0976, 1983, 10, 7, /* 0 1 1 0 1 1 1 0 1 0 0 1 10/7/1983
128 1405*/0x056C, 1984, 9, 26, /* 0 0 1 1 0 1 1 0 1 0 1 0 9/26/1984
129 1406*/0x0B55, 1985, 9, 15, /* 1 0 1 0 1 0 1 0 1 1 0 1 9/15/1985
130 1407*/0x0AAA, 1986, 9, 5, /* 0 1 0 1 0 1 0 1 0 1 0 1 9/5/1986
131 1408*/0x0A55, 1987, 8, 25, /* 1 0 1 0 1 0 1 0 0 1 0 1 8/25/1987
132 1409*/0x04AD, 1988, 8, 13, /* 1 0 1 1 0 1 0 1 0 0 1 0 8/13/1988
133 1410*/0x095D, 1989, 8, 2, /* 1 0 1 1 1 0 1 0 1 0 0 1 8/2/1989
134 1411*/0x02DA, 1990, 7, 23, /* 0 1 0 1 1 0 1 1 0 1 0 0 7/23/1990
135 1412*/0x05D9, 1991, 7, 12, /* 1 0 0 1 1 0 1 1 1 0 1 0 7/12/1991
136 1413*/0x0DB2, 1992, 7, 1, /* 0 1 0 0 1 1 0 1 1 0 1 1 7/1/1992
137 1414*/0x0BA4, 1993, 6, 21, /* 0 0 1 0 0 1 0 1 1 1 0 1 6/21/1993
138 1415*/0x0B4A, 1994, 6, 10, /* 0 1 0 1 0 0 1 0 1 1 0 1 6/10/1994
139 1416*/0x0A55, 1995, 5, 30, /* 1 0 1 0 1 0 1 0 0 1 0 1 5/30/1995
140 1417*/0x02B5, 1996, 5, 18, /* 1 0 1 0 1 1 0 1 0 1 0 0 5/18/1996
141 1418*/0x0575, 1997, 5, 7, /* 1 0 1 0 1 1 1 0 1 0 1 0 5/7/1997
142 1419*/0x0B6A, 1998, 4, 27, /* 0 1 0 1 0 1 1 0 1 1 0 1 4/27/1998
143 1420*/0x0BD2, 1999, 4, 17, /* 0 1 0 0 1 0 1 1 1 1 0 1 4/17/1999
144 1421*/0x0BC4, 2000, 4, 6, /* 0 0 1 0 0 0 1 1 1 1 0 1 4/6/2000
145 1422*/0x0B89, 2001, 3, 26, /* 1 0 0 1 0 0 0 1 1 1 0 1 3/26/2001
146 1423*/0x0A95, 2002, 3, 15, /* 1 0 1 0 1 0 0 1 0 1 0 1 3/15/2002
147 1424*/0x052D, 2003, 3, 4, /* 1 0 1 1 0 1 0 0 1 0 1 0 3/4/2003
148 1425*/0x05AD, 2004, 2, 21, /* 1 0 1 1 0 1 0 1 1 0 1 0 2/21/2004
149 1426*/0x0B6A, 2005, 2, 10, /* 0 1 0 1 0 1 1 0 1 1 0 1 2/10/2005
150 1427*/0x06D4, 2006, 1, 31, /* 0 0 1 0 1 0 1 1 0 1 1 0 1/31/2006
151 1428*/0x0DC9, 2007, 1, 20, /* 1 0 0 1 0 0 1 1 1 0 1 1 1/20/2007
152 1429*/0x0D92, 2008, 1, 10, /* 0 1 0 0 1 0 0 1 1 0 1 1 1/10/2008
153 1430*/0x0AA6, 2008, 12, 29, /* 0 1 1 0 0 1 0 1 0 1 0 1 12/29/2008
154 1431*/0x0956, 2009, 12, 18, /* 0 1 1 0 1 0 1 0 1 0 0 1 12/18/2009
155 1432*/0x02AE, 2010, 12, 7, /* 0 1 1 1 0 1 0 1 0 1 0 0 12/7/2010
156 1433*/0x056D, 2011, 11, 26, /* 1 0 1 1 0 1 1 0 1 0 1 0 11/26/2011
157 1434*/0x036A, 2012, 11, 15, /* 0 1 0 1 0 1 1 0 1 1 0 0 11/15/2012
158 1435*/0x0B55, 2013, 11, 4, /* 1 0 1 0 1 0 1 0 1 1 0 1 11/4/2013
159 1436*/0x0AAA, 2014, 10, 25, /* 0 1 0 1 0 1 0 1 0 1 0 1 10/25/2014
160 1437*/0x094D, 2015, 10, 14, /* 1 0 1 1 0 0 1 0 1 0 0 1 10/14/2015
161 1438*/0x049D, 2016, 10, 2, /* 1 0 1 1 1 0 0 1 0 0 1 0 10/2/2016
162 1439*/0x095D, 2017, 9, 21, /* 1 0 1 1 1 0 1 0 1 0 0 1 9/21/2017
163 1440*/0x02BA, 2018, 9, 11, /* 0 1 0 1 1 1 0 1 0 1 0 0 9/11/2018
164 1441*/0x05B5, 2019, 8, 31, /* 1 0 1 0 1 1 0 1 1 0 1 0 8/31/2019
165 1442*/0x05AA, 2020, 8, 20, /* 0 1 0 1 0 1 0 1 1 0 1 0 8/20/2020
166 1443*/0x0D55, 2021, 8, 9, /* 1 0 1 0 1 0 1 0 1 0 1 1 8/9/2021
167 1444*/0x0A9A, 2022, 7, 30, /* 0 1 0 1 1 0 0 1 0 1 0 1 7/30/2022
168 1445*/0x092E, 2023, 7, 19, /* 0 1 1 1 0 1 0 0 1 0 0 1 7/19/2023
169 1446*/0x026E, 2024, 7, 7, /* 0 1 1 1 0 1 1 0 0 1 0 0 7/7/2024
170 1447*/0x055D, 2025, 6, 26, /* 1 0 1 1 1 0 1 0 1 0 1 0 6/26/2025
171 1448*/0x0ADA, 2026, 6, 16, /* 0 1 0 1 1 0 1 1 0 1 0 1 6/16/2026
172 1449*/0x06D4, 2027, 6, 6, /* 0 0 1 0 1 0 1 1 0 1 1 0 6/6/2027
173 1450*/0x06A5, 2028, 5, 25, /* 1 0 1 0 0 1 0 1 0 1 1 0 5/25/2028
174 1451*/0x054B, 2029, 5, 14, /* 1 1 0 1 0 0 1 0 1 0 1 0 5/14/2029
175 1452*/0x0A97, 2030, 5, 3, /* 1 1 1 0 1 0 0 1 0 1 0 1 5/3/2030
176 1453*/0x054E, 2031, 4, 23, /* 0 1 1 1 0 0 1 0 1 0 1 0 4/23/2031
177 1454*/0x0AAE, 2032, 4, 11, /* 0 1 1 1 0 1 0 1 0 1 0 1 4/11/2032
178 1455*/0x05AC, 2033, 4, 1, /* 0 0 1 1 0 1 0 1 1 0 1 0 4/1/2033
179 1456*/0x0BA9, 2034, 3, 21, /* 1 0 0 1 0 1 0 1 1 1 0 1 3/21/2034
180 1457*/0x0D92, 2035, 3, 11, /* 0 1 0 0 1 0 0 1 1 0 1 1 3/11/2035
181 1458*/0x0B25, 2036, 2, 28, /* 1 0 1 0 0 1 0 0 1 1 0 1 2/28/2036
182 1459*/0x064B, 2037, 2, 16, /* 1 1 0 1 0 0 1 0 0 1 1 0 2/16/2037
183 1460*/0x0CAB, 2038, 2, 5, /* 1 1 0 1 0 1 0 1 0 0 1 1 2/5/2038
184 1461*/0x055A, 2039, 1, 26, /* 0 1 0 1 1 0 1 0 1 0 1 0 1/26/2039
185 1462*/0x0B55, 2040, 1, 15, /* 1 0 1 0 1 0 1 0 1 1 0 1 1/15/2040
186 1463*/0x06D2, 2041, 1, 4, /* 0 1 0 0 1 0 1 1 0 1 1 0 1/4/2041
187 1464*/0x0EA5, 2041, 12, 24, /* 1 0 1 0 0 1 0 1 0 1 1 1 12/24/2041
188 1465*/0x0E4A, 2042, 12, 14, /* 0 1 0 1 0 0 1 0 0 1 1 1 12/14/2042
189 1466*/0x0A95, 2043, 12, 3, /* 1 0 1 0 1 0 0 1 0 1 0 1 12/3/2043
190 1467*/0x052D, 2044, 11, 21, /* 1 0 1 1 0 1 0 0 1 0 1 0 11/21/2044
191 1468*/0x0AAD, 2045, 11, 10, /* 1 0 1 1 0 1 0 1 0 1 0 1 11/10/2045
192 1469*/0x036C, 2046, 10, 31, /* 0 0 1 1 0 1 1 0 1 1 0 0 10/31/2046
193 1470*/0x0759, 2047, 10, 20, /* 1 0 0 1 1 0 1 0 1 1 1 0 10/20/2047
194 1471*/0x06D2, 2048, 10, 9, /* 0 1 0 0 1 0 1 1 0 1 1 0 10/9/2048
195 1472*/0x0695, 2049, 9, 28, /* 1 0 1 0 1 0 0 1 0 1 1 0 9/28/2049
196 1473*/0x052D, 2050, 9, 17, /* 1 0 1 1 0 1 0 0 1 0 1 0 9/17/2050
197 1474*/0x0A5B, 2051, 9, 6, /* 1 1 0 1 1 0 1 0 0 1 0 1 9/6/2051
198 1475*/0x04BA, 2052, 8, 26, /* 0 1 0 1 1 1 0 1 0 0 1 0 8/26/2052
199 1476*/0x09BA, 2053, 8, 15, /* 0 1 0 1 1 1 0 1 1 0 0 1 8/15/2053
200 1477*/0x03B4, 2054, 8, 5, /* 0 0 1 0 1 1 0 1 1 1 0 0 8/5/2054
201 1478*/0x0B69, 2055, 7, 25, /* 1 0 0 1 0 1 1 0 1 1 0 1 7/25/2055
202 1479*/0x0B52, 2056, 7, 14, /* 0 1 0 0 1 0 1 0 1 1 0 1 7/14/2056
203 1480*/0x0AA6, 2057, 7, 3, /* 0 1 1 0 0 1 0 1 0 1 0 1 7/3/2057
204 1481*/0x04B6, 2058, 6, 22, /* 0 1 1 0 1 1 0 1 0 0 1 0 6/22/2058
205 1482*/0x096D, 2059, 6, 11, /* 1 0 1 1 0 1 1 0 1 0 0 1 6/11/2059
206 1483*/0x02EC, 2060, 5, 31, /* 0 0 1 1 0 1 1 1 0 1 0 0 5/31/2060
207 1484*/0x06D9, 2061, 5, 20, /* 1 0 0 1 1 0 1 1 0 1 1 0 5/20/2061
208 1485*/0x0EB2, 2062, 5, 10, /* 0 1 0 0 1 1 0 1 0 1 1 1 5/10/2062
209 1486*/0x0D54, 2063, 4, 30, /* 0 0 1 0 1 0 1 0 1 0 1 1 4/30/2063
210 1487*/0x0D2A, 2064, 4, 18, /* 0 1 0 1 0 1 0 0 1 0 1 1 4/18/2064
211 1488*/0x0A56, 2065, 4, 7, /* 0 1 1 0 1 0 1 0 0 1 0 1 4/7/2065
212 1489*/0x04AE, 2066, 3, 27, /* 0 1 1 1 0 1 0 1 0 0 1 0 3/27/2066
213 1490*/0x096D, 2067, 3, 16, /* 1 0 1 1 0 1 1 0 1 0 0 1 3/16/2067
214 1491*/0x0D6A, 2068, 3, 5, /* 0 1 0 1 0 1 1 0 1 0 1 1 3/5/2068
215 1492*/0x0B54, 2069, 2, 23, /* 0 0 1 0 1 0 1 0 1 1 0 1 2/23/2069
216 1493*/0x0B29, 2070, 2, 12, /* 1 0 0 1 0 1 0 0 1 1 0 1 2/12/2070
217 1494*/0x0A93, 2071, 2, 1, /* 1 1 0 0 1 0 0 1 0 1 0 1 2/1/2071
218 1495*/0x052B, 2072, 1, 21, /* 1 1 0 1 0 1 0 0 1 0 1 0 1/21/2072
219 1496*/0x0A57, 2073, 1, 9, /* 1 1 1 0 1 0 1 0 0 1 0 1 1/9/2073
220 1497*/0x0536, 2073, 12, 30, /* 0 1 1 0 1 1 0 0 1 0 1 0 12/30/2073
221 1498*/0x0AB5, 2074, 12, 19, /* 1 0 1 0 1 1 0 1 0 1 0 1 12/19/2074
222 1499*/0x06AA, 2075, 12, 9, /* 0 1 0 1 0 1 0 1 0 1 1 0 12/9/2075
223 1500*/0x0E93, 2076, 11, 27, /* 1 1 0 0 1 0 0 1 0 1 1 1 11/27/2076
224 1501*/ 0, 2077, 11, 17, /* 0 0 0 0 0 0 0 0 0 0 0 0 11/17/2077
225 */ };
226 // Direct inline initialization of DateMapping array would produce a lot of code bloat.
228 // We take advantage of C# compiler compiles inline initialization of primitive type array into very compact code.
229 // So we start with raw data stored in primitive type array, and initialize the DateMapping out of it
231 DateMapping[] mapping = new DateMapping[rawData.Length / 4];
232 for (int i = 0; i < mapping.Length; i++)
233 mapping[i] = new DateMapping(rawData[i * 4], rawData[i * 4 + 1], rawData[i * 4 + 2], rawData[i * 4 + 3]);
234 return mapping;
237 public const int UmAlQuraEra = 1;
239 private const int DatePartYear = 0;
240 private const int DatePartDayOfYear = 1;
241 private const int DatePartMonth = 2;
242 private const int DatePartDay = 3;
244 private static readonly DateTime s_minDate = new DateTime(1900, 4, 30);
245 private static readonly DateTime s_maxDate = new DateTime((new DateTime(2077, 11, 16, 23, 59, 59, 999)).Ticks + 9999);
247 public override DateTime MinSupportedDateTime => s_minDate;
249 public override DateTime MaxSupportedDateTime => s_maxDate;
251 public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunarCalendar;
253 public UmAlQuraCalendar()
257 internal override CalendarId BaseCalendarID => CalendarId.HIJRI;
259 internal override CalendarId ID => CalendarId.UMALQURA;
261 protected override int DaysInYearBeforeMinSupportedYear =>
262 // HijriCalendar has same number of days as UmAlQuraCalendar for any given year
263 // HijriCalendar says year 1317 has 355 days.
264 355;
266 private static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, out int yg, out int mg, out int dg)
268 Debug.Assert((HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range.");
269 Debug.Assert(HijriMonth >= 1, "Hijri month is out of range.");
270 Debug.Assert(HijriDay >= 1, "Hijri day is out of range.");
271 int nDays = HijriDay - 1;
273 int index = HijriYear - MinCalendarYear;
274 DateTime dt = s_hijriYearInfo[index].GregorianDate;
275 int b = s_hijriYearInfo[index].HijriMonthsLengthFlags;
277 for (int m = 1; m < HijriMonth; m++)
279 // Add the months lengths before mh
280 nDays = nDays + 29 + (b & 1);
281 b >>= 1;
284 dt = dt.AddDays(nDays);
285 dt.GetDatePart(out yg, out mg, out dg);
288 private static long GetAbsoluteDateUmAlQura(int year, int month, int day)
290 ConvertHijriToGregorian(year, month, day, out int yg, out int mg, out int dg);
291 return GregorianCalendar.GetAbsoluteDate(yg, mg, dg);
294 internal static void CheckTicksRange(long ticks)
296 if (ticks < s_minDate.Ticks || ticks > s_maxDate.Ticks)
298 throw new ArgumentOutOfRangeException(
299 "time",
300 ticks,
301 SR.Format(
302 CultureInfo.InvariantCulture,
303 SR.ArgumentOutOfRange_CalendarRange,
304 s_minDate,
305 s_maxDate));
309 internal static void CheckEraRange(int era)
311 if (era != CurrentEra && era != UmAlQuraEra)
313 throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
317 internal static void CheckYearRange(int year, int era)
319 CheckEraRange(era);
320 if (year < MinCalendarYear || year > MaxCalendarYear)
322 throw new ArgumentOutOfRangeException(
323 nameof(year),
324 year,
325 SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
329 internal static void CheckYearMonthRange(int year, int month, int era)
331 CheckYearRange(year, era);
332 if (month < 1 || month > 12)
334 throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
338 private static void ConvertGregorianToHijri(DateTime time, out int HijriYear, out int HijriMonth, out int HijriDay)
340 Debug.Assert((time.Ticks >= s_minDate.Ticks) && (time.Ticks <= s_maxDate.Ticks), "Gregorian date is out of range.");
342 // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearInfo.
343 // A Hijri year is 354 or 355 days. Use 355 days so that we will search from a lower index.
345 int index = (int)((time.Ticks - s_minDate.Ticks) / Calendar.TicksPerDay) / 355;
348 } while (time.CompareTo(s_hijriYearInfo[++index].GregorianDate) > 0); // while greater
350 if (time.CompareTo(s_hijriYearInfo[index].GregorianDate) != 0)
352 index--;
355 TimeSpan ts = time.Subtract(s_hijriYearInfo[index].GregorianDate);
356 int yh1 = index + MinCalendarYear;
357 int mh1 = 1;
358 int dh1 = 1;
359 double nDays = ts.TotalDays;
360 int b = s_hijriYearInfo[index].HijriMonthsLengthFlags;
361 int daysPerThisMonth = 29 + (b & 1);
363 while (nDays >= daysPerThisMonth)
365 nDays -= daysPerThisMonth;
366 b >>= 1;
367 daysPerThisMonth = 29 + (b & 1);
368 mh1++;
370 dh1 += (int)nDays;
372 HijriDay = dh1;
373 HijriMonth = mh1;
374 HijriYear = yh1;
377 /// <summary>
378 /// First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
379 /// Use the formula (((AbsoluteDate - 226894) * 33) / (33 * 365 + 8)) + 1, we can a rough value for the UmAlQura year.
380 /// In order to get the exact UmAlQura year, we compare the exact absolute date for UmAlQuraYear and (UmAlQuraYear + 1).
381 /// From here, we can get the correct UmAlQura year.
382 /// </summary>
383 private int GetDatePart(DateTime time, int part)
385 long ticks = time.Ticks;
386 CheckTicksRange(ticks);
388 ConvertGregorianToHijri(time, out int UmAlQuraYear, out int UmAlQuraMonth, out int UmAlQuraDay);
390 if (part == DatePartYear)
392 return UmAlQuraYear;
394 if (part == DatePartMonth)
396 return UmAlQuraMonth;
398 if (part == DatePartDay)
400 return UmAlQuraDay;
402 if (part == DatePartDayOfYear)
404 return (int)(GetAbsoluteDateUmAlQura(UmAlQuraYear, UmAlQuraMonth, UmAlQuraDay) - GetAbsoluteDateUmAlQura(UmAlQuraYear, 1, 1) + 1);
407 // Incorrect part value.
408 throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
411 public override DateTime AddMonths(DateTime time, int months)
413 if (months < -120000 || months > 120000)
415 throw new ArgumentOutOfRangeException(
416 nameof(months),
417 months,
418 SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
421 // Get the date in UmAlQura calendar.
422 int y = GetDatePart(time, DatePartYear);
423 int m = GetDatePart(time, DatePartMonth);
424 int d = GetDatePart(time, DatePartDay);
425 int i = m - 1 + months;
427 if (i >= 0)
429 m = i % 12 + 1;
430 y += i / 12;
432 else
434 m = 12 + (i + 1) % 12;
435 y += (i - 11) / 12;
438 if (d > 29)
440 int days = GetDaysInMonth(y, m);
441 if (d > days)
443 d = days;
447 CheckYearRange(y, UmAlQuraEra);
448 DateTime dt = new DateTime(GetAbsoluteDateUmAlQura(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay);
449 Calendar.CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
450 return dt;
453 public override DateTime AddYears(DateTime time, int years)
455 return AddMonths(time, years * 12);
458 public override int GetDayOfMonth(DateTime time)
460 return GetDatePart(time, DatePartDay);
463 public override DayOfWeek GetDayOfWeek(DateTime time)
465 return (DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7);
468 public override int GetDayOfYear(DateTime time)
470 return GetDatePart(time, DatePartDayOfYear);
473 public override int GetDaysInMonth(int year, int month, int era)
475 CheckYearMonthRange(year, month, era);
477 if ((s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags & (1 << month - 1)) == 0)
479 return 29;
481 else
483 return 30;
487 internal static int RealGetDaysInYear(int year)
489 int days = 0;
491 Debug.Assert((year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range.");
493 int b = s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags;
495 for (int m = 1; m <= 12; m++)
497 days = days + 29 + (b & 1); /* Add the months lengths before mh */
498 b >>= 1;
501 Debug.Assert((days == 354) || (days == 355), "Hijri year has to be 354 or 355 days.");
502 return days;
505 public override int GetDaysInYear(int year, int era)
507 CheckYearRange(year, era);
508 return RealGetDaysInYear(year);
511 public override int GetEra(DateTime time)
513 CheckTicksRange(time.Ticks);
514 return UmAlQuraEra;
517 public override int[] Eras => new int[] { UmAlQuraEra };
519 public override int GetMonth(DateTime time)
521 return GetDatePart(time, DatePartMonth);
524 public override int GetMonthsInYear(int year, int era)
526 CheckYearRange(year, era);
527 return 12;
530 public override int GetYear(DateTime time)
532 return GetDatePart(time, DatePartYear);
535 public override bool IsLeapDay(int year, int month, int day, int era)
537 if (day >= 1 && day <= 29)
539 CheckYearMonthRange(year, month, era);
540 return false;
543 // The year/month/era value checking is done in GetDaysInMonth().
544 int daysInMonth = GetDaysInMonth(year, month, era);
545 if (day < 1 || day > daysInMonth)
547 throw new ArgumentOutOfRangeException(
548 nameof(day),
549 day,
550 SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
552 return false;
555 public override int GetLeapMonth(int year, int era)
557 CheckYearRange(year, era);
558 return 0;
561 public override bool IsLeapMonth(int year, int month, int era)
563 CheckYearMonthRange(year, month, era);
564 return false;
567 public override bool IsLeapYear(int year, int era)
569 CheckYearRange(year, era);
570 return RealGetDaysInYear(year) == 355;
573 public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
575 if (day >= 1 && day <= 29)
577 CheckYearMonthRange(year, month, era);
578 goto DayInRang;
581 // The year/month/era value checking is done in GetDaysInMonth().
582 int daysInMonth = GetDaysInMonth(year, month, era);
584 if (day < 1 || day > daysInMonth)
586 throw new ArgumentOutOfRangeException(
587 nameof(day),
588 day,
589 SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
591 DayInRang:
592 long lDate = GetAbsoluteDateUmAlQura(year, month, day);
593 if (lDate < 0)
595 throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
598 return new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond));
601 private const int DefaultTwoDigitYearMax = 1451;
603 public override int TwoDigitYearMax
607 if (_twoDigitYearMax == -1)
609 _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
612 return _twoDigitYearMax;
616 if (value != 99 && (value < MinCalendarYear || value > MaxCalendarYear))
618 throw new ArgumentOutOfRangeException(
619 nameof(value),
620 value,
621 SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
624 VerifyWritable();
625 // We allow year 99 to be set so that one can make ToFourDigitYearMax a no-op by setting TwoDigitYearMax to 99.
626 _twoDigitYearMax = value;
630 public override int ToFourDigitYear(int year)
632 if (year < 0)
634 throw new ArgumentOutOfRangeException(nameof(year), year, SR.ArgumentOutOfRange_NeedNonNegNum);
637 if (year < 100)
639 return base.ToFourDigitYear(year);
642 if (year < MinCalendarYear || year > MaxCalendarYear)
644 throw new ArgumentOutOfRangeException(
645 nameof(year),
646 year,
647 SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
650 return year;