< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 376
Coverable lines: 376
Total lines: 647
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 88
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Private.CoreLib/src/System/Globalization/UmAlQuraCalendar.cs

#LineLine coverage
 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
 4using System.Diagnostics;
 5
 6namespace System.Globalization
 7{
 8    /// <remarks>
 9    /// Calendar support range:
 10    ///     Calendar    Minimum     Maximum
 11    ///     ==========  ==========  ==========
 12    ///     Gregorian   1900/04/30   2077/05/13
 13    ///     UmAlQura    1318/01/01   1500/12/30
 14    /// </remarks>
 15    public partial class UmAlQuraCalendar : Calendar
 16    {
 17        private const int MinCalendarYear = 1318;
 18        private const int MaxCalendarYear = 1500;
 19
 20        private readonly struct DateMapping
 21        {
 22            internal DateMapping(int MonthsLengthFlags, int GYear, int GMonth, int GDay)
 23            {
 024                HijriMonthsLengthFlags = MonthsLengthFlags;
 025                GregorianDate = new DateTime(GYear, GMonth, GDay);
 026            }
 27
 28            internal readonly int HijriMonthsLengthFlags;
 29            internal readonly DateTime GregorianDate;
 30        }
 31
 032        private static readonly DateMapping[] s_hijriYearInfo = InitDateMapping();
 33
 34        private static DateMapping[] InitDateMapping()
 35        {
 036            ReadOnlySpan<short> rawData =
 037            [
 038                // These data are taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync
 039                /*  DaysPerM     GY      GM     GD      D1   D2   D3   D4   D5   D6   D7   D8   D9   D10  D11  D12
 040                1318*/0x02EA,    1900,     4,    30, /* 0    1    0    1    0    1    1    1    0    1    0    0    4/30
 041                1319*/0x06E9,    1901,     4,    19, /* 1    0    0    1    0    1    1    1    0    1    1    0    4/19
 042                1320*/0x0ED2,    1902,     4,     9, /* 0    1    0    0    1    0    1    1    0    1    1    1    4/9/
 043                1321*/0x0EA4,    1903,     3,    30, /* 0    0    1    0    0    1    0    1    0    1    1    1    3/30
 044                1322*/0x0D4A,    1904,     3,    18, /* 0    1    0    1    0    0    1    0    1    0    1    1    3/18
 045                1323*/0x0A96,    1905,     3,     7, /* 0    1    1    0    1    0    0    1    0    1    0    1    3/7/
 046                1324*/0x0536,    1906,     2,    24, /* 0    1    1    0    1    1    0    0    1    0    1    0    2/24
 047                1325*/0x0AB5,    1907,     2,    13, /* 1    0    1    0    1    1    0    1    0    1    0    1    2/13
 048                1326*/0x0DAA,    1908,     2,     3, /* 0    1    0    1    0    1    0    1    1    0    1    1    2/3/
 049                1327*/0x0BA4,    1909,     1,    23, /* 0    0    1    0    0    1    0    1    1    1    0    1    1/23
 050                1328*/0x0B49,    1910,     1,    12, /* 1    0    0    1    0    0    1    0    1    1    0    1    1/12
 051                1329*/0x0A93,    1911,     1,     1, /* 1    1    0    0    1    0    0    1    0    1    0    1    1/1/
 052                1330*/0x052B,    1911,    12,    21, /* 1    1    0    1    0    1    0    0    1    0    1    0    12/2
 053                1331*/0x0A57,    1912,    12,     9, /* 1    1    1    0    1    0    1    0    0    1    0    1    12/9
 054                1332*/0x04B6,    1913,    11,    29, /* 0    1    1    0    1    1    0    1    0    0    1    0    11/2
 055                1333*/0x0AB5,    1914,    11,    18, /* 1    0    1    0    1    1    0    1    0    1    0    1    11/1
 056                1334*/0x05AA,    1915,    11,     8, /* 0    1    0    1    0    1    0    1    1    0    1    0    11/8
 057                1335*/0x0D55,    1916,    10,    27, /* 1    0    1    0    1    0    1    0    1    0    1    1    10/2
 058                1336*/0x0D2A,    1917,    10,    17, /* 0    1    0    1    0    1    0    0    1    0    1    1    10/1
 059                1337*/0x0A56,    1918,    10,     6, /* 0    1    1    0    1    0    1    0    0    1    0    1    10/6
 060                1338*/0x04AE,    1919,     9,    25, /* 0    1    1    1    0    1    0    1    0    0    1    0    9/25
 061                1339*/0x095D,    1920,     9,    13, /* 1    0    1    1    1    0    1    0    1    0    0    1    9/13
 062                1340*/0x02EC,    1921,     9,     3, /* 0    0    1    1    0    1    1    1    0    1    0    0    9/3/
 063                1341*/0x06D5,    1922,     8,    23, /* 1    0    1    0    1    0    1    1    0    1    1    0    8/23
 064                1342*/0x06AA,    1923,     8,    13, /* 0    1    0    1    0    1    0    1    0    1    1    0    8/13
 065                1343*/0x0555,    1924,     8,     1, /* 1    0    1    0    1    0    1    0    1    0    1    0    8/1/
 066                1344*/0x04AB,    1925,     7,    21, /* 1    1    0    1    0    1    0    1    0    0    1    0    7/21
 067                1345*/0x095B,    1926,     7,    10, /* 1    1    0    1    1    0    1    0    1    0    0    1    7/10
 068                1346*/0x02BA,    1927,     6,    30, /* 0    1    0    1    1    1    0    1    0    1    0    0    6/30
 069                1347*/0x0575,    1928,     6,    18, /* 1    0    1    0    1    1    1    0    1    0    1    0    6/18
 070                1348*/0x0BB2,    1929,     6,     8, /* 0    1    0    0    1    1    0    1    1    1    0    1    6/8/
 071                1349*/0x0764,    1930,     5,    29, /* 0    0    1    0    0    1    1    0    1    1    1    0    5/29
 072                1350*/0x0749,    1931,     5,    18, /* 1    0    0    1    0    0    1    0    1    1    1    0    5/18
 073                1351*/0x0655,    1932,     5,     6, /* 1    0    1    0    1    0    1    0    0    1    1    0    5/6/
 074                1352*/0x02AB,    1933,     4,    25, /* 1    1    0    1    0    1    0    1    0    1    0    0    4/25
 075                1353*/0x055B,    1934,     4,    14, /* 1    1    0    1    1    0    1    0    1    0    1    0    4/14
 076                1354*/0x0ADA,    1935,     4,     4, /* 0    1    0    1    1    0    1    1    0    1    0    1    4/4/
 077                1355*/0x06D4,    1936,     3,    24, /* 0    0    1    0    1    0    1    1    0    1    1    0    3/24
 078                1356*/0x0EC9,    1937,     3,    13, /* 1    0    0    1    0    0    1    1    0    1    1    1    3/13
 079                1357*/0x0D92,    1938,     3,     3, /* 0    1    0    0    1    0    0    1    1    0    1    1    3/3/
 080                1358*/0x0D25,    1939,     2,    20, /* 1    0    1    0    0    1    0    0    1    0    1    1    2/20
 081                1359*/0x0A4D,    1940,     2,     9, /* 1    0    1    1    0    0    1    0    0    1    0    1    2/9/
 082                1360*/0x02AD,    1941,     1,    28, /* 1    0    1    1    0    1    0    1    0    1    0    0    1/28
 083                1361*/0x056D,    1942,     1,    17, /* 1    0    1    1    0    1    1    0    1    0    1    0    1/17
 084                1362*/0x0B6A,    1943,     1,     7, /* 0    1    0    1    0    1    1    0    1    1    0    1    1/7/
 085                1363*/0x0B52,    1943,    12,    28, /* 0    1    0    0    1    0    1    0    1    1    0    1    12/2
 086                1364*/0x0AA5,    1944,    12,    16, /* 1    0    1    0    0    1    0    1    0    1    0    1    12/1
 087                1365*/0x0A4B,    1945,    12,     5, /* 1    1    0    1    0    0    1    0    0    1    0    1    12/5
 088                1366*/0x0497,    1946,    11,    24, /* 1    1    1    0    1    0    0    1    0    0    1    0    11/2
 089                1367*/0x0937,    1947,    11,    13, /* 1    1    1    0    1    1    0    0    1    0    0    1    11/1
 090                1368*/0x02B6,    1948,    11,     2, /* 0    1    1    0    1    1    0    1    0    1    0    0    11/2
 091                1369*/0x0575,    1949,    10,    22, /* 1    0    1    0    1    1    1    0    1    0    1    0    10/2
 092                1370*/0x0D6A,    1950,    10,    12, /* 0    1    0    1    0    1    1    0    1    0    1    1    10/1
 093                1371*/0x0D52,    1951,    10,     2, /* 0    1    0    0    1    0    1    0    1    0    1    1    10/2
 094                1372*/0x0A96,    1952,     9,    20, /* 0    1    1    0    1    0    0    1    0    1    0    1    9/20
 095                1373*/0x092D,    1953,     9,     9, /* 1    0    1    1    0    1    0    0    1    0    0    1    9/9/
 096                1374*/0x025D,    1954,     8,    29, /* 1    0    1    1    1    0    1    0    0    1    0    0    8/29
 097                1375*/0x04DD,    1955,     8,    18, /* 1    0    1    1    1    0    1    1    0    0    1    0    8/18
 098                1376*/0x0ADA,    1956,     8,     7, /* 0    1    0    1    1    0    1    1    0    1    0    1    8/7/
 099                1377*/0x05D4,    1957,     7,    28, /* 0    0    1    0    1    0    1    1    1    0    1    0    7/28
 0100                1378*/0x0DA9,    1958,     7,    17, /* 1    0    0    1    0    1    0    1    1    0    1    1    7/17
 0101                1379*/0x0D52,    1959,     7,     7, /* 0    1    0    0    1    0    1    0    1    0    1    1    7/7/
 0102                1380*/0x0AAA,    1960,     6,    25, /* 0    1    0    1    0    1    0    1    0    1    0    1    6/25
 0103                1381*/0x04D6,    1961,     6,    14, /* 0    1    1    0    1    0    1    1    0    0    1    0    6/14
 0104                1382*/0x09B6,    1962,     6,     3, /* 0    1    1    0    1    1    0    1    1    0    0    1    6/3/
 0105                1383*/0x0374,    1963,     5,    24, /* 0    0    1    0    1    1    1    0    1    1    0    0    5/24
 0106                1384*/0x0769,    1964,     5,    12, /* 1    0    0    1    0    1    1    0    1    1    1    0    5/12
 0107                1385*/0x0752,    1965,     5,     2, /* 0    1    0    0    1    0    1    0    1    1    1    0    5/2/
 0108                1386*/0x06A5,    1966,     4,    21, /* 1    0    1    0    0    1    0    1    0    1    1    0    4/21
 0109                1387*/0x054B,    1967,     4,    10, /* 1    1    0    1    0    0    1    0    1    0    1    0    4/10
 0110                1388*/0x0AAB,    1968,     3,    29, /* 1    1    0    1    0    1    0    1    0    1    0    1    3/29
 0111                1389*/0x055A,    1969,     3,    19, /* 0    1    0    1    1    0    1    0    1    0    1    0    3/19
 0112                1390*/0x0AD5,    1970,     3,     8, /* 1    0    1    0    1    0    1    1    0    1    0    1    3/8/
 0113                1391*/0x0DD2,    1971,     2,    26, /* 0    1    0    0    1    0    1    1    1    0    1    1    2/26
 0114                1392*/0x0DA4,    1972,     2,    16, /* 0    0    1    0    0    1    0    1    1    0    1    1    2/16
 0115                1393*/0x0D49,    1973,     2,     4, /* 1    0    0    1    0    0    1    0    1    0    1    1    2/4/
 0116                1394*/0x0A95,    1974,     1,    24, /* 1    0    1    0    1    0    0    1    0    1    0    1    1/24
 0117                1395*/0x052D,    1975,     1,    13, /* 1    0    1    1    0    1    0    0    1    0    1    0    1/13
 0118                1396*/0x0A5D,    1976,     1,     2, /* 1    0    1    1    1    0    1    0    0    1    0    1    1/2/
 0119                1397*/0x055A,    1976,    12,    22, /* 0    1    0    1    1    0    1    0    1    0    1    0    12/2
 0120                1398*/0x0AD5,    1977,    12,    11, /* 1    0    1    0    1    0    1    1    0    1    0    1    12/1
 0121                1399*/0x06AA,    1978,    12,     1, /* 0    1    0    1    0    1    0    1    0    1    1    0    12/1
 0122                1400*/0x0695,    1979,    11,    20, /* 1    0    1    0    1    0    0    1    0    1    1    0    11/2
 0123                1401*/0x052B,    1980,    11,     8, /* 1    1    0    1    0    1    0    0    1    0    1    0    11/8
 0124                1402*/0x0A57,    1981,    10,    28, /* 1    1    1    0    1    0    1    0    0    1    0    1    10/2
 0125                1403*/0x04AE,    1982,    10,    18, /* 0    1    1    1    0    1    0    1    0    0    1    0    10/1
 0126                1404*/0x0976,    1983,    10,     7, /* 0    1    1    0    1    1    1    0    1    0    0    1    10/7
 0127                1405*/0x056C,    1984,     9,    26, /* 0    0    1    1    0    1    1    0    1    0    1    0    9/26
 0128                1406*/0x0B55,    1985,     9,    15, /* 1    0    1    0    1    0    1    0    1    1    0    1    9/15
 0129                1407*/0x0AAA,    1986,     9,     5, /* 0    1    0    1    0    1    0    1    0    1    0    1    9/5/
 0130                1408*/0x0A55,    1987,     8,    25, /* 1    0    1    0    1    0    1    0    0    1    0    1    8/25
 0131                1409*/0x04AD,    1988,     8,    13, /* 1    0    1    1    0    1    0    1    0    0    1    0    8/13
 0132                1410*/0x095D,    1989,     8,     2, /* 1    0    1    1    1    0    1    0    1    0    0    1    8/2/
 0133                1411*/0x02DA,    1990,     7,    23, /* 0    1    0    1    1    0    1    1    0    1    0    0    7/23
 0134                1412*/0x05D9,    1991,     7,    12, /* 1    0    0    1    1    0    1    1    1    0    1    0    7/12
 0135                1413*/0x0DB2,    1992,     7,     1, /* 0    1    0    0    1    1    0    1    1    0    1    1    7/1/
 0136                1414*/0x0BA4,    1993,     6,    21, /* 0    0    1    0    0    1    0    1    1    1    0    1    6/21
 0137                1415*/0x0B4A,    1994,     6,    10, /* 0    1    0    1    0    0    1    0    1    1    0    1    6/10
 0138                1416*/0x0A55,    1995,     5,    30, /* 1    0    1    0    1    0    1    0    0    1    0    1    5/30
 0139                1417*/0x02B5,    1996,     5,    18, /* 1    0    1    0    1    1    0    1    0    1    0    0    5/18
 0140                1418*/0x0575,    1997,     5,     7, /* 1    0    1    0    1    1    1    0    1    0    1    0    5/7/
 0141                1419*/0x0B6A,    1998,     4,    27, /* 0    1    0    1    0    1    1    0    1    1    0    1    4/27
 0142                1420*/0x0BD2,    1999,     4,    17, /* 0    1    0    0    1    0    1    1    1    1    0    1    4/17
 0143                1421*/0x0BC4,    2000,     4,     6, /* 0    0    1    0    0    0    1    1    1    1    0    1    4/6/
 0144                1422*/0x0B89,    2001,     3,    26, /* 1    0    0    1    0    0    0    1    1    1    0    1    3/26
 0145                1423*/0x0A95,    2002,     3,    15, /* 1    0    1    0    1    0    0    1    0    1    0    1    3/15
 0146                1424*/0x052D,    2003,     3,     4, /* 1    0    1    1    0    1    0    0    1    0    1    0    3/4/
 0147                1425*/0x05AD,    2004,     2,    21, /* 1    0    1    1    0    1    0    1    1    0    1    0    2/21
 0148                1426*/0x0B6A,    2005,     2,    10, /* 0    1    0    1    0    1    1    0    1    1    0    1    2/10
 0149                1427*/0x06D4,    2006,     1,    31, /* 0    0    1    0    1    0    1    1    0    1    1    0    1/31
 0150                1428*/0x0DC9,    2007,     1,    20, /* 1    0    0    1    0    0    1    1    1    0    1    1    1/20
 0151                1429*/0x0D92,    2008,     1,    10, /* 0    1    0    0    1    0    0    1    1    0    1    1    1/10
 0152                1430*/0x0AA6,    2008,    12,    29, /* 0    1    1    0    0    1    0    1    0    1    0    1    12/2
 0153                1431*/0x0956,    2009,    12,    18, /* 0    1    1    0    1    0    1    0    1    0    0    1    12/1
 0154                1432*/0x02AE,    2010,    12,     7, /* 0    1    1    1    0    1    0    1    0    1    0    0    12/7
 0155                1433*/0x056D,    2011,    11,    26, /* 1    0    1    1    0    1    1    0    1    0    1    0    11/2
 0156                1434*/0x036A,    2012,    11,    15, /* 0    1    0    1    0    1    1    0    1    1    0    0    11/1
 0157                1435*/0x0B55,    2013,    11,     4, /* 1    0    1    0    1    0    1    0    1    1    0    1    11/4
 0158                1436*/0x0AAA,    2014,    10,    25, /* 0    1    0    1    0    1    0    1    0    1    0    1    10/2
 0159                1437*/0x094D,    2015,    10,    14, /* 1    0    1    1    0    0    1    0    1    0    0    1    10/1
 0160                1438*/0x049D,    2016,    10,     2, /* 1    0    1    1    1    0    0    1    0    0    1    0    10/2
 0161                1439*/0x095D,    2017,     9,    21, /* 1    0    1    1    1    0    1    0    1    0    0    1    9/21
 0162                1440*/0x02BA,    2018,     9,    11, /* 0    1    0    1    1    1    0    1    0    1    0    0    9/11
 0163                1441*/0x05B5,    2019,     8,    31, /* 1    0    1    0    1    1    0    1    1    0    1    0    8/31
 0164                1442*/0x05AA,    2020,     8,    20, /* 0    1    0    1    0    1    0    1    1    0    1    0    8/20
 0165                1443*/0x0D55,    2021,     8,     9, /* 1    0    1    0    1    0    1    0    1    0    1    1    8/9/
 0166                1444*/0x0A9A,    2022,     7,    30, /* 0    1    0    1    1    0    0    1    0    1    0    1    7/30
 0167                1445*/0x092E,    2023,     7,    19, /* 0    1    1    1    0    1    0    0    1    0    0    1    7/19
 0168                1446*/0x026E,    2024,     7,     7, /* 0    1    1    1    0    1    1    0    0    1    0    0    7/7/
 0169                1447*/0x055D,    2025,     6,    26, /* 1    0    1    1    1    0    1    0    1    0    1    0    6/26
 0170                1448*/0x0ADA,    2026,     6,    16, /* 0    1    0    1    1    0    1    1    0    1    0    1    6/16
 0171                1449*/0x06D4,    2027,     6,     6, /* 0    0    1    0    1    0    1    1    0    1    1    0    6/6/
 0172                1450*/0x06A5,    2028,     5,    25, /* 1    0    1    0    0    1    0    1    0    1    1    0    5/25
 0173                1451*/0x054B,    2029,     5,    14, /* 1    1    0    1    0    0    1    0    1    0    1    0    5/14
 0174                1452*/0x0A97,    2030,     5,     3, /* 1    1    1    0    1    0    0    1    0    1    0    1    5/3/
 0175                1453*/0x054E,    2031,     4,    23, /* 0    1    1    1    0    0    1    0    1    0    1    0    4/23
 0176                1454*/0x0AAE,    2032,     4,    11, /* 0    1    1    1    0    1    0    1    0    1    0    1    4/11
 0177                1455*/0x05AC,    2033,     4,     1, /* 0    0    1    1    0    1    0    1    1    0    1    0    4/1/
 0178                1456*/0x0BA9,    2034,     3,    21, /* 1    0    0    1    0    1    0    1    1    1    0    1    3/21
 0179                1457*/0x0D92,    2035,     3,    11, /* 0    1    0    0    1    0    0    1    1    0    1    1    3/11
 0180                1458*/0x0B25,    2036,     2,    28, /* 1    0    1    0    0    1    0    0    1    1    0    1    2/28
 0181                1459*/0x064B,    2037,     2,    16, /* 1    1    0    1    0    0    1    0    0    1    1    0    2/16
 0182                1460*/0x0CAB,    2038,     2,     5, /* 1    1    0    1    0    1    0    1    0    0    1    1    2/5/
 0183                1461*/0x055A,    2039,     1,    26, /* 0    1    0    1    1    0    1    0    1    0    1    0    1/26
 0184                1462*/0x0B55,    2040,     1,    15, /* 1    0    1    0    1    0    1    0    1    1    0    1    1/15
 0185                1463*/0x06D2,    2041,     1,     4, /* 0    1    0    0    1    0    1    1    0    1    1    0    1/4/
 0186                1464*/0x0EA5,    2041,     12,   24, /* 1    0    1    0    0    1    0    1    0    1    1    1    12/2
 0187                1465*/0x0E4A,    2042,     12,   14, /* 0    1    0    1    0    0    1    0    0    1    1    1    12/1
 0188                1466*/0x0A95,    2043,     12,    3, /* 1    0    1    0    1    0    0    1    0    1    0    1    12/3
 0189                1467*/0x052D,    2044,     11,   21, /* 1    0    1    1    0    1    0    0    1    0    1    0    11/2
 0190                1468*/0x0AAD,    2045,     11,   10, /* 1    0    1    1    0    1    0    1    0    1    0    1    11/1
 0191                1469*/0x036C,    2046,     10,   31, /* 0    0    1    1    0    1    1    0    1    1    0    0    10/3
 0192                1470*/0x0759,    2047,     10,   20, /* 1    0    0    1    1    0    1    0    1    1    1    0    10/2
 0193                1471*/0x06D2,    2048,     10,    9, /* 0    1    0    0    1    0    1    1    0    1    1    0    10/9
 0194                1472*/0x0695,    2049,     9,    28, /* 1    0    1    0    1    0    0    1    0    1    1    0    9/28
 0195                1473*/0x052D,    2050,     9,    17, /* 1    0    1    1    0    1    0    0    1    0    1    0    9/17
 0196                1474*/0x0A5B,    2051,     9,     6, /* 1    1    0    1    1    0    1    0    0    1    0    1    9/6/
 0197                1475*/0x04BA,    2052,     8,    26, /* 0    1    0    1    1    1    0    1    0    0    1    0    8/26
 0198                1476*/0x09BA,    2053,     8,    15, /* 0    1    0    1    1    1    0    1    1    0    0    1    8/15
 0199                1477*/0x03B4,    2054,     8,     5, /* 0    0    1    0    1    1    0    1    1    1    0    0    8/5/
 0200                1478*/0x0B69,    2055,     7,    25, /* 1    0    0    1    0    1    1    0    1    1    0    1    7/25
 0201                1479*/0x0B52,    2056,     7,    14, /* 0    1    0    0    1    0    1    0    1    1    0    1    7/14
 0202                1480*/0x0AA6,    2057,     7,     3, /* 0    1    1    0    0    1    0    1    0    1    0    1    7/3/
 0203                1481*/0x04B6,    2058,     6,    22, /* 0    1    1    0    1    1    0    1    0    0    1    0    6/22
 0204                1482*/0x096D,    2059,     6,    11, /* 1    0    1    1    0    1    1    0    1    0    0    1    6/11
 0205                1483*/0x02EC,    2060,     5,    31, /* 0    0    1    1    0    1    1    1    0    1    0    0    5/31
 0206                1484*/0x06D9,    2061,     5,    20, /* 1    0    0    1    1    0    1    1    0    1    1    0    5/20
 0207                1485*/0x0EB2,    2062,     5,    10, /* 0    1    0    0    1    1    0    1    0    1    1    1    5/10
 0208                1486*/0x0D54,    2063,     4,    30, /* 0    0    1    0    1    0    1    0    1    0    1    1    4/30
 0209                1487*/0x0D2A,    2064,     4,    18, /* 0    1    0    1    0    1    0    0    1    0    1    1    4/18
 0210                1488*/0x0A56,    2065,     4,     7, /* 0    1    1    0    1    0    1    0    0    1    0    1    4/7/
 0211                1489*/0x04AE,    2066,     3,    27, /* 0    1    1    1    0    1    0    1    0    0    1    0    3/27
 0212                1490*/0x096D,    2067,     3,    16, /* 1    0    1    1    0    1    1    0    1    0    0    1    3/16
 0213                1491*/0x0D6A,    2068,     3,     5, /* 0    1    0    1    0    1    1    0    1    0    1    1    3/5/
 0214                1492*/0x0B54,    2069,     2,    23, /* 0    0    1    0    1    0    1    0    1    1    0    1    2/23
 0215                1493*/0x0B29,    2070,     2,    12, /* 1    0    0    1    0    1    0    0    1    1    0    1    2/12
 0216                1494*/0x0A93,    2071,     2,     1, /* 1    1    0    0    1    0    0    1    0    1    0    1    2/1/
 0217                1495*/0x052B,    2072,     1,    21, /* 1    1    0    1    0    1    0    0    1    0    1    0    1/21
 0218                1496*/0x0A57,    2073,     1,     9, /* 1    1    1    0    1    0    1    0    0    1    0    1    1/9/
 0219                1497*/0x0536,    2073,     12,   30, /* 0    1    1    0    1    1    0    0    1    0    1    0    12/3
 0220                1498*/0x0AB5,    2074,     12,   19, /* 1    0    1    0    1    1    0    1    0    1    0    1    12/1
 0221                1499*/0x06AA,    2075,     12,    9, /* 0    1    0    1    0    1    0    1    0    1    1    0    12/9
 0222                1500*/0x0E93,    2076,     11,   27, /* 1    1    0    0    1    0    0    1    0    1    1    1    11/2
 0223                1501*/     0,    2077,     11,   17, /* 0    0    0    0    0    0    0    0    0    0    0    0    11/1
 0224    */      ];
 225            // Direct inline initialization of DateMapping array would produce a lot of code bloat.
 226
 227            // We take advantage of C# compiler blitting primitive span data into assembly data.
 228            // So we start with raw data stored in primitive type span, and initialize the DateMapping out of it
 229
 0230            DateMapping[] mapping = new DateMapping[rawData.Length / 4];
 0231            for (int i = 0; i < mapping.Length; i++)
 0232                mapping[i] = new DateMapping(rawData[i * 4], rawData[i * 4 + 1], rawData[i * 4 + 2], rawData[i * 4 + 3])
 0233            return mapping;
 234        }
 235
 236        public const int UmAlQuraEra = 1;
 237
 238        private const int DatePartYear = 0;
 239        private const int DatePartDayOfYear = 1;
 240        private const int DatePartMonth = 2;
 241        private const int DatePartDay = 3;
 242
 0243        private static readonly DateTime s_minDate = new DateTime(1900, 4, 30);
 0244        private static readonly DateTime s_maxDate = new DateTime((new DateTime(2077, 11, 16, 23, 59, 59, 999)).Ticks + 
 245
 0246        public override DateTime MinSupportedDateTime => s_minDate;
 247
 0248        public override DateTime MaxSupportedDateTime => s_maxDate;
 249
 0250        public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunarCalendar;
 251
 0252        public UmAlQuraCalendar()
 253        {
 0254        }
 255
 0256        internal override CalendarId BaseCalendarID => CalendarId.HIJRI;
 257
 0258        internal override CalendarId ID => CalendarId.UMALQURA;
 259
 260        protected override int DaysInYearBeforeMinSupportedYear =>
 261            // HijriCalendar has same number of days as UmAlQuraCalendar for any given year
 262            // HijriCalendar says year 1317 has 355 days.
 0263            355;
 264
 265        private static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, out int yg, out int mg,
 266        {
 0267            Debug.Assert((HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range."
 0268            Debug.Assert(HijriMonth >= 1, "Hijri month is out of range.");
 0269            Debug.Assert(HijriDay >= 1, "Hijri day is out of range.");
 0270            int nDays = HijriDay - 1;
 271
 0272            int index = HijriYear - MinCalendarYear;
 0273            DateTime dt = s_hijriYearInfo[index].GregorianDate;
 0274            int b = s_hijriYearInfo[index].HijriMonthsLengthFlags;
 275
 0276            for (int m = 1; m < HijriMonth; m++)
 277            {
 278                // Add the months lengths before mh
 0279                nDays = nDays + 29 + (b & 1);
 0280                b >>= 1;
 281            }
 282
 0283            dt = dt.AddDays(nDays);
 0284            dt.GetDate(out yg, out mg, out dg);
 0285        }
 286
 287        private static long GetAbsoluteDateUmAlQura(int year, int month, int day)
 288        {
 0289            ConvertHijriToGregorian(year, month, day, out int yg, out int mg, out int dg);
 0290            return GregorianCalendar.GetAbsoluteDate(yg, mg, dg);
 291        }
 292
 293        internal static void CheckTicksRange(long ticks)
 294        {
 0295            if (ticks < s_minDate.Ticks || ticks > s_maxDate.Ticks)
 296            {
 0297                throw new ArgumentOutOfRangeException(
 0298                    "time",
 0299                    ticks,
 0300                    SR.Format(
 0301                        CultureInfo.InvariantCulture,
 0302                        SR.ArgumentOutOfRange_CalendarRange,
 0303                        s_minDate,
 0304                        s_maxDate));
 305            }
 0306        }
 307
 308        internal static void CheckEraRange(int era)
 309        {
 0310            if (era != CurrentEra && era != UmAlQuraEra)
 311            {
 0312                throw new ArgumentOutOfRangeException(nameof(era), era, SR.ArgumentOutOfRange_InvalidEraValue);
 313            }
 0314        }
 315
 316        internal static void CheckYearRange(int year, int era)
 317        {
 0318            CheckEraRange(era);
 0319            if (year < MinCalendarYear || year > MaxCalendarYear)
 320            {
 0321                throw new ArgumentOutOfRangeException(
 0322                    nameof(year),
 0323                    year,
 0324                    SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
 325            }
 0326        }
 327
 328        internal static void CheckYearMonthRange(int year, int month, int era)
 329        {
 0330            CheckYearRange(year, era);
 0331            if (month < 1 || month > 12)
 332            {
 0333                ThrowHelper.ThrowArgumentOutOfRange_Month(month);
 334            }
 0335        }
 336
 337        private static void ConvertGregorianToHijri(DateTime time, out int HijriYear, out int HijriMonth, out int HijriD
 338        {
 0339            Debug.Assert((time.Ticks >= s_minDate.Ticks) && (time.Ticks <= s_maxDate.Ticks), "Gregorian date is out of r
 340
 341            // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearIn
 342            // A Hijri year is 354 or 355 days.  Use 355 days so that we will search from a lower index.
 343
 0344            int index = (int)((time.Ticks - s_minDate.Ticks) / TimeSpan.TicksPerDay) / 355;
 345            do
 346            {
 0347            } while (time.CompareTo(s_hijriYearInfo[++index].GregorianDate) > 0); // while greater
 348
 0349            if (time.CompareTo(s_hijriYearInfo[index].GregorianDate) != 0)
 350            {
 0351                index--;
 352            }
 353
 0354            TimeSpan ts = time.Subtract(s_hijriYearInfo[index].GregorianDate);
 0355            int yh1 = index + MinCalendarYear;
 0356            int mh1 = 1;
 0357            int dh1 = 1;
 0358            double nDays = ts.TotalDays;
 0359            int b = s_hijriYearInfo[index].HijriMonthsLengthFlags;
 0360            int daysPerThisMonth = 29 + (b & 1);
 361
 0362            while (nDays >= daysPerThisMonth)
 363            {
 0364                nDays -= daysPerThisMonth;
 0365                b >>= 1;
 0366                daysPerThisMonth = 29 + (b & 1);
 0367                mh1++;
 368            }
 0369            dh1 += (int)nDays;
 370
 0371            HijriDay = dh1;
 0372            HijriMonth = mh1;
 0373            HijriYear = yh1;
 0374        }
 375
 376        /// <summary>
 377        /// First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
 378        /// Use the formula (((AbsoluteDate - 226894) * 33) / (33 * 365 + 8)) + 1, we can a rough value for the UmAlQura
 379        /// In order to get the exact UmAlQura year, we compare the exact absolute date for UmAlQuraYear and (UmAlQuraYe
 380        /// From here, we can get the correct UmAlQura year.
 381        /// </summary>
 382        private static int GetDatePart(DateTime time, int part)
 383        {
 0384            long ticks = time.Ticks;
 0385            CheckTicksRange(ticks);
 386
 0387            ConvertGregorianToHijri(time, out int UmAlQuraYear, out int UmAlQuraMonth, out int UmAlQuraDay);
 388
 0389            if (part == DatePartYear)
 390            {
 0391                return UmAlQuraYear;
 392            }
 0393            if (part == DatePartMonth)
 394            {
 0395                return UmAlQuraMonth;
 396            }
 0397            if (part == DatePartDay)
 398            {
 0399                return UmAlQuraDay;
 400            }
 0401            if (part == DatePartDayOfYear)
 402            {
 0403                return (int)(GetAbsoluteDateUmAlQura(UmAlQuraYear, UmAlQuraMonth, UmAlQuraDay) - GetAbsoluteDateUmAlQura
 404            }
 405
 406            // Incorrect part value.
 0407            throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
 408        }
 409
 410        public override DateTime AddMonths(DateTime time, int months)
 411        {
 0412            if (months < -120000 || months > 120000)
 413            {
 0414                throw new ArgumentOutOfRangeException(
 0415                    nameof(months),
 0416                    months,
 0417                    SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
 418            }
 419
 420            // Get the date in UmAlQura calendar.
 0421            int y = GetDatePart(time, DatePartYear);
 0422            int m = GetDatePart(time, DatePartMonth);
 0423            int d = GetDatePart(time, DatePartDay);
 0424            int i = m - 1 + months;
 425
 0426            if (i >= 0)
 427            {
 0428                m = i % 12 + 1;
 0429                y += i / 12;
 430            }
 431            else
 432            {
 0433                m = 12 + (i + 1) % 12;
 0434                y += (i - 11) / 12;
 435            }
 436
 0437            if (d > 29)
 438            {
 0439                int days = GetDaysInMonth(y, m);
 0440                if (d > days)
 441                {
 0442                    d = days;
 443                }
 444            }
 445
 0446            CheckYearRange(y, UmAlQuraEra);
 0447            DateTime dt = new DateTime(GetAbsoluteDateUmAlQura(y, m, d) * TimeSpan.TicksPerDay + time.Ticks % TimeSpan.T
 0448            CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
 0449            return dt;
 450        }
 451
 452        public override DateTime AddYears(DateTime time, int years)
 453        {
 0454            return AddMonths(time, years * 12);
 455        }
 456
 457        public override int GetDayOfMonth(DateTime time)
 458        {
 0459            return GetDatePart(time, DatePartDay);
 460        }
 461
 0462        public override DayOfWeek GetDayOfWeek(DateTime time) => time.DayOfWeek;
 463
 464        public override int GetDayOfYear(DateTime time)
 465        {
 0466            return GetDatePart(time, DatePartDayOfYear);
 467        }
 468
 469        public override int GetDaysInMonth(int year, int month, int era)
 470        {
 0471            CheckYearMonthRange(year, month, era);
 472
 0473            if ((s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags & (1 << month - 1)) == 0)
 474            {
 0475                return 29;
 476            }
 477            else
 478            {
 0479                return 30;
 480            }
 481        }
 482
 483        internal static int RealGetDaysInYear(int year)
 484        {
 0485            int days = 0;
 486
 0487            Debug.Assert((year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range.");
 488
 0489            int b = s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags;
 490
 0491            for (int m = 1; m <= 12; m++)
 492            {
 0493                days = days + 29 + (b & 1);   /* Add the months lengths before mh */
 0494                b >>= 1;
 495            }
 496
 0497            Debug.Assert((days == 354) || (days == 355), "Hijri year has to be 354 or 355 days.");
 0498            return days;
 499        }
 500
 501        public override int GetDaysInYear(int year, int era)
 502        {
 0503            CheckYearRange(year, era);
 0504            return RealGetDaysInYear(year);
 505        }
 506
 507        public override int GetEra(DateTime time)
 508        {
 0509            CheckTicksRange(time.Ticks);
 0510            return UmAlQuraEra;
 511        }
 512
 0513        public override int[] Eras => [UmAlQuraEra];
 514
 515        public override int GetMonth(DateTime time)
 516        {
 0517            return GetDatePart(time, DatePartMonth);
 518        }
 519
 520        public override int GetMonthsInYear(int year, int era)
 521        {
 0522            CheckYearRange(year, era);
 0523            return 12;
 524        }
 525
 526        public override int GetYear(DateTime time)
 527        {
 0528            return GetDatePart(time, DatePartYear);
 529        }
 530
 531        public override bool IsLeapDay(int year, int month, int day, int era)
 532        {
 0533            if (day >= 1 && day <= 29)
 534            {
 0535                CheckYearMonthRange(year, month, era);
 0536                return false;
 537            }
 538
 539            // The year/month/era value checking is done in GetDaysInMonth().
 0540            int daysInMonth = GetDaysInMonth(year, month, era);
 0541            if (day < 1 || day > daysInMonth)
 542            {
 0543                throw new ArgumentOutOfRangeException(
 0544                    nameof(day),
 0545                    day,
 0546                    SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
 547            }
 0548            return false;
 549        }
 550
 551        public override int GetLeapMonth(int year, int era)
 552        {
 0553            CheckYearRange(year, era);
 0554            return 0;
 555        }
 556
 557        public override bool IsLeapMonth(int year, int month, int era)
 558        {
 0559            CheckYearMonthRange(year, month, era);
 0560            return false;
 561        }
 562
 563        public override bool IsLeapYear(int year, int era)
 564        {
 0565            CheckYearRange(year, era);
 0566            return RealGetDaysInYear(year) == 355;
 567        }
 568
 569        public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisec
 570        {
 0571            if (day >= 1 && day <= 29)
 572            {
 0573                CheckYearMonthRange(year, month, era);
 0574                goto DayInRang;
 575            }
 576
 577            // The year/month/era value checking is done in GetDaysInMonth().
 0578            int daysInMonth = GetDaysInMonth(year, month, era);
 579
 0580            if (day < 1 || day > daysInMonth)
 581            {
 0582                throw new ArgumentOutOfRangeException(
 0583                    nameof(day),
 0584                    day,
 0585                    SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
 586            }
 587        DayInRang:
 0588            long lDate = GetAbsoluteDateUmAlQura(year, month, day);
 0589            if (lDate < 0)
 590            {
 0591                throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
 592            }
 593
 0594            return new DateTime(lDate * TimeSpan.TicksPerDay + TimeToTicks(hour, minute, second, millisecond));
 595        }
 596
 597        private const int DefaultTwoDigitYearMax = 1451;
 598
 599        public override int TwoDigitYearMax
 600        {
 601            get
 602            {
 0603                if (_twoDigitYearMax == -1)
 604                {
 0605                    _twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DefaultTwoDigitYearMax);
 606                }
 607
 0608                return _twoDigitYearMax;
 609            }
 610            set
 611            {
 0612                if (value != 99 && (value < MinCalendarYear || value > MaxCalendarYear))
 613                {
 0614                    throw new ArgumentOutOfRangeException(
 0615                        nameof(value),
 0616                        value,
 0617                        SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
 618                }
 619
 0620                VerifyWritable();
 621                // We allow year 99 to be set so that one can make ToFourDigitYearMax a no-op by setting TwoDigitYearMax
 0622                _twoDigitYearMax = value;
 0623            }
 624        }
 625
 626        public override int ToFourDigitYear(int year)
 627        {
 0628            ArgumentOutOfRangeException.ThrowIfNegative(year);
 629
 0630            if (year < 100)
 631            {
 0632                return base.ToFourDigitYear(year);
 633            }
 634
 0635            if (year < MinCalendarYear || year > MaxCalendarYear)
 636            {
 0637                throw new ArgumentOutOfRangeException(
 0638                    nameof(year),
 0639                    year,
 0640                    SR.Format(SR.ArgumentOutOfRange_Range, MinCalendarYear, MaxCalendarYear));
 641            }
 642
 0643            return year;
 644        }
 645    }
 646}
 647