tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

islamcal.cpp (41989B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 ******************************************************************************
      5 * Copyright (C) 2003-2015, International Business Machines Corporation
      6 * and others. All Rights Reserved.
      7 ******************************************************************************
      8 *
      9 * File ISLAMCAL.H
     10 *
     11 * Modification History:
     12 *
     13 *   Date        Name        Description
     14 *   10/14/2003  srl         ported from java IslamicCalendar
     15 *****************************************************************************
     16 */
     17 
     18 #include "islamcal.h"
     19 
     20 #if !UCONFIG_NO_FORMATTING
     21 
     22 #include "umutex.h"
     23 #include <float.h>
     24 #include "gregoimp.h" // Math
     25 #include "astro.h" // CalendarAstronomer
     26 #include "uhash.h"
     27 #include "ucln_in.h"
     28 #include "uassert.h"
     29 
     30 static const UDate HIJRA_MILLIS = -42521587200000.0;    // 7/16/622 AD 00:00
     31 
     32 // Debugging
     33 #ifdef U_DEBUG_ISLAMCAL
     34 # include <stdio.h>
     35 # include <stdarg.h>
     36 static void debug_islamcal_loc(const char *f, int32_t l)
     37 {
     38    fprintf(stderr, "%s:%d: ", f, l);
     39 }
     40 
     41 static void debug_islamcal_msg(const char *pat, ...)
     42 {
     43    va_list ap;
     44    va_start(ap, pat);
     45    vfprintf(stderr, pat, ap);
     46    fflush(stderr);
     47 }
     48 // must use double parens, i.e.:  U_DEBUG_ISLAMCAL_MSG(("four is: %d",4));
     49 #define U_DEBUG_ISLAMCAL_MSG(x) {debug_islamcal_loc(__FILE__,__LINE__);debug_islamcal_msg x;}
     50 #else
     51 #define U_DEBUG_ISLAMCAL_MSG(x)
     52 #endif
     53 
     54 
     55 // --- The cache --
     56 // cache of months
     57 static icu::CalendarCache *gMonthCache = nullptr;
     58 
     59 U_CDECL_BEGIN
     60 static UBool calendar_islamic_cleanup() {
     61    if (gMonthCache) {
     62        delete gMonthCache;
     63        gMonthCache = nullptr;
     64    }
     65    return true;
     66 }
     67 U_CDECL_END
     68 
     69 U_NAMESPACE_BEGIN
     70 
     71 // Implementation of the IslamicCalendar class
     72 
     73 /**
     74 * Friday EPOC
     75 */
     76 static const int32_t CIVIL_EPOC = 1948440; // CE 622 July 16 Friday (Julian calendar) / CE 622 July 19 (Gregorian calendar)
     77 
     78 /**
     79  * Thursday EPOC
     80  */
     81 static const int32_t ASTRONOMICAL_EPOC = 1948439; // CE 622 July 15 Thursday (Julian calendar)
     82 
     83 
     84 static const int32_t UMALQURA_YEAR_START = 1300;
     85 static const int32_t UMALQURA_YEAR_END = 1600;
     86 
     87 static const int UMALQURA_MONTHLENGTH[] = {
     88    //* 1300 -1302 */ "1010 1010 1010", "1101 0101 0100", "1110 1100 1001",
     89                            0x0AAA,           0x0D54,           0x0EC9,
     90    //* 1303 -1307 */ "0110 1101 0100", "0110 1110 1010", "0011 0110 1100", "1010 1010 1101", "0101 0101 0101",
     91                            0x06D4,           0x06EA,           0x036C,           0x0AAD,           0x0555,
     92    //* 1308 -1312 */ "0110 1010 1001", "0111 1001 0010", "1011 1010 1001", "0101 1101 0100", "1010 1101 1010",
     93                            0x06A9,           0x0792,           0x0BA9,           0x05D4,           0x0ADA,
     94    //* 1313 -1317 */ "0101 0101 1100", "1101 0010 1101", "0110 1001 0101", "0111 0100 1010", "1011 0101 0100",
     95                            0x055C,           0x0D2D,           0x0695,           0x074A,           0x0B54,
     96    //* 1318 -1322 */ "1011 0110 1010", "0101 1010 1101", "0100 1010 1110", "1010 0100 1111", "0101 0001 0111",
     97                            0x0B6A,           0x05AD,           0x04AE,           0x0A4F,           0x0517,
     98    //* 1323 -1327 */ "0110 1000 1011", "0110 1010 0101", "1010 1101 0101", "0010 1101 0110", "1001 0101 1011",
     99                            0x068B,           0x06A5,           0x0AD5,           0x02D6,           0x095B,
    100    //* 1328 -1332 */ "0100 1001 1101", "1010 0100 1101", "1101 0010 0110", "1101 1001 0101", "0101 1010 1100",
    101                            0x049D,           0x0A4D,           0x0D26,           0x0D95,           0x05AC,
    102    //* 1333 -1337 */ "1001 1011 0110", "0010 1011 1010", "1010 0101 1011", "0101 0010 1011", "1010 1001 0101",
    103                            0x09B6,           0x02BA,           0x0A5B,           0x052B,           0x0A95,
    104    //* 1338 -1342 */ "0110 1100 1010", "1010 1110 1001", "0010 1111 0100", "1001 0111 0110", "0010 1011 0110",
    105                            0x06CA,           0x0AE9,           0x02F4,           0x0976,           0x02B6,
    106    //* 1343 -1347 */ "1001 0101 0110", "1010 1100 1010", "1011 1010 0100", "1011 1101 0010", "0101 1101 1001",
    107                            0x0956,           0x0ACA,           0x0BA4,           0x0BD2,           0x05D9,
    108    //* 1348 -1352 */ "0010 1101 1100", "1001 0110 1101", "0101 0100 1101", "1010 1010 0101", "1011 0101 0010",
    109                            0x02DC,           0x096D,           0x054D,           0x0AA5,           0x0B52,
    110    //* 1353 -1357 */ "1011 1010 0101", "0101 1011 0100", "1001 1011 0110", "0101 0101 0111", "0010 1001 0111",
    111                            0x0BA5,           0x05B4,           0x09B6,           0x0557,           0x0297,
    112    //* 1358 -1362 */ "0101 0100 1011", "0110 1010 0011", "0111 0101 0010", "1011 0110 0101", "0101 0110 1010",
    113                            0x054B,           0x06A3,           0x0752,           0x0B65,           0x056A,
    114    //* 1363 -1367 */ "1010 1010 1011", "0101 0010 1011", "1100 1001 0101", "1101 0100 1010", "1101 1010 0101",
    115                            0x0AAB,           0x052B,           0x0C95,           0x0D4A,           0x0DA5,
    116    //* 1368 -1372 */ "0101 1100 1010", "1010 1101 0110", "1001 0101 0111", "0100 1010 1011", "1001 0100 1011",
    117                            0x05CA,           0x0AD6,           0x0957,           0x04AB,           0x094B,
    118    //* 1373 -1377 */ "1010 1010 0101", "1011 0101 0010", "1011 0110 1010", "0101 0111 0101", "0010 0111 0110",
    119                            0x0AA5,           0x0B52,           0x0B6A,           0x0575,           0x0276,
    120    //* 1378 -1382 */ "1000 1011 0111", "0100 0101 1011", "0101 0101 0101", "0101 1010 1001", "0101 1011 0100",
    121                            0x08B7,           0x045B,           0x0555,           0x05A9,           0x05B4,
    122    //* 1383 -1387 */ "1001 1101 1010", "0100 1101 1101", "0010 0110 1110", "1001 0011 0110", "1010 1010 1010",
    123                            0x09DA,           0x04DD,           0x026E,           0x0936,           0x0AAA,
    124    //* 1388 -1392 */ "1101 0101 0100", "1101 1011 0010", "0101 1101 0101", "0010 1101 1010", "1001 0101 1011",
    125                            0x0D54,           0x0DB2,           0x05D5,           0x02DA,           0x095B,
    126    //* 1393 -1397 */ "0100 1010 1011", "1010 0101 0101", "1011 0100 1001", "1011 0110 0100", "1011 0111 0001",
    127                            0x04AB,           0x0A55,           0x0B49,           0x0B64,           0x0B71,
    128    //* 1398 -1402 */ "0101 1011 0100", "1010 1011 0101", "1010 0101 0101", "1101 0010 0101", "1110 1001 0010",
    129                            0x05B4,           0x0AB5,           0x0A55,           0x0D25,           0x0E92,
    130    //* 1403 -1407 */ "1110 1100 1001", "0110 1101 0100", "1010 1110 1001", "1001 0110 1011", "0100 1010 1011",
    131                            0x0EC9,           0x06D4,           0x0AE9,           0x096B,           0x04AB,
    132    //* 1408 -1412 */ "1010 1001 0011", "1101 0100 1001", "1101 1010 0100", "1101 1011 0010", "1010 1011 1001",
    133                            0x0A93,           0x0D49,         0x0DA4,           0x0DB2,           0x0AB9,
    134    //* 1413 -1417 */ "0100 1011 1010", "1010 0101 1011", "0101 0010 1011", "1010 1001 0101", "1011 0010 1010",
    135                            0x04BA,           0x0A5B,           0x052B,           0x0A95,           0x0B2A,
    136    //* 1418 -1422 */ "1011 0101 0101", "0101 0101 1100", "0100 1011 1101", "0010 0011 1101", "1001 0001 1101",
    137                            0x0B55,           0x055C,           0x04BD,           0x023D,           0x091D,
    138    //* 1423 -1427 */ "1010 1001 0101", "1011 0100 1010", "1011 0101 1010", "0101 0110 1101", "0010 1011 0110",
    139                            0x0A95,           0x0B4A,           0x0B5A,           0x056D,           0x02B6,
    140    //* 1428 -1432 */ "1001 0011 1011", "0100 1001 1011", "0110 0101 0101", "0110 1010 1001", "0111 0101 0100",
    141                            0x093B,           0x049B,           0x0655,           0x06A9,           0x0754,
    142    //* 1433 -1437 */ "1011 0110 1010", "0101 0110 1100", "1010 1010 1101", "0101 0101 0101", "1011 0010 1001",
    143                            0x0B6A,           0x056C,           0x0AAD,           0x0555,           0x0B29,
    144    //* 1438 -1442 */ "1011 1001 0010", "1011 1010 1001", "0101 1101 0100", "1010 1101 1010", "0101 0101 1010",
    145                            0x0B92,           0x0BA9,           0x05D4,           0x0ADA,           0x055A,
    146    //* 1443 -1447 */ "1010 1010 1011", "0101 1001 0101", "0111 0100 1001", "0111 0110 0100", "1011 1010 1010",
    147                            0x0AAB,           0x0595,           0x0749,           0x0764,           0x0BAA,
    148    //* 1448 -1452 */ "0101 1011 0101", "0010 1011 0110", "1010 0101 0110", "1110 0100 1101", "1011 0010 0101",
    149                            0x05B5,           0x02B6,           0x0A56,           0x0E4D,           0x0B25,
    150    //* 1453 -1457 */ "1011 0101 0010", "1011 0110 1010", "0101 1010 1101", "0010 1010 1110", "1001 0010 1111",
    151                            0x0B52,           0x0B6A,           0x05AD,           0x02AE,           0x092F,
    152    //* 1458 -1462 */ "0100 1001 0111", "0110 0100 1011", "0110 1010 0101", "0110 1010 1100", "1010 1101 0110",
    153                            0x0497,           0x064B,           0x06A5,           0x06AC,           0x0AD6,
    154    //* 1463 -1467 */ "0101 0101 1101", "0100 1001 1101", "1010 0100 1101", "1101 0001 0110", "1101 1001 0101",
    155                            0x055D,           0x049D,           0x0A4D,           0x0D16,           0x0D95,
    156    //* 1468 -1472 */ "0101 1010 1010", "0101 1011 0101", "0010 1101 1010", "1001 0101 1011", "0100 1010 1101",
    157                            0x05AA,           0x05B5,           0x02DA,           0x095B,           0x04AD,
    158    //* 1473 -1477 */ "0101 1001 0101", "0110 1100 1010", "0110 1110 0100", "1010 1110 1010", "0100 1111 0101",
    159                            0x0595,           0x06CA,           0x06E4,           0x0AEA,           0x04F5,
    160    //* 1478 -1482 */ "0010 1011 0110", "1001 0101 0110", "1010 1010 1010", "1011 0101 0100", "1011 1101 0010",
    161                            0x02B6,           0x0956,           0x0AAA,           0x0B54,           0x0BD2,
    162    //* 1483 -1487 */ "0101 1101 1001", "0010 1110 1010", "1001 0110 1101", "0100 1010 1101", "1010 1001 0101",
    163                            0x05D9,           0x02EA,           0x096D,           0x04AD,           0x0A95,
    164    //* 1488 -1492 */ "1011 0100 1010", "1011 1010 0101", "0101 1011 0010", "1001 1011 0101", "0100 1101 0110",
    165                            0x0B4A,           0x0BA5,           0x05B2,           0x09B5,           0x04D6,
    166    //* 1493 -1497 */ "1010 1001 0111", "0101 0100 0111", "0110 1001 0011", "0111 0100 1001", "1011 0101 0101",
    167                            0x0A97,           0x0547,           0x0693,           0x0749,           0x0B55,
    168    //* 1498 -1508 */ "0101 0110 1010", "1010 0110 1011", "0101 0010 1011", "1010 1000 1011", "1101 0100 0110", "1101 1010 0011", "0101 1100 1010", "1010 1101 0110", "0100 1101 1011", "0010 0110 1011", "1001 0100 1011",
    169                            0x056A,           0x0A6B,           0x052B,           0x0A8B,           0x0D46,           0x0DA3,           0x05CA,           0x0AD6,           0x04DB,           0x026B,           0x094B,
    170    //* 1509 -1519 */ "1010 1010 0101", "1011 0101 0010", "1011 0110 1001", "0101 0111 0101", "0001 0111 0110", "1000 1011 0111", "0010 0101 1011", "0101 0010 1011", "0101 0110 0101", "0101 1011 0100", "1001 1101 1010",
    171                            0x0AA5,           0x0B52,           0x0B69,           0x0575,           0x0176,           0x08B7,           0x025B,           0x052B,           0x0565,           0x05B4,           0x09DA,
    172    //* 1520 -1530 */ "0100 1110 1101", "0001 0110 1101", "1000 1011 0110", "1010 1010 0110", "1101 0101 0010", "1101 1010 1001", "0101 1101 0100", "1010 1101 1010", "1001 0101 1011", "0100 1010 1011", "0110 0101 0011",
    173                            0x04ED,           0x016D,           0x08B6,           0x0AA6,           0x0D52,           0x0DA9,           0x05D4,           0x0ADA,           0x095B,           0x04AB,           0x0653,
    174    //* 1531 -1541 */ "0111 0010 1001", "0111 0110 0010", "1011 1010 1001", "0101 1011 0010", "1010 1011 0101", "0101 0101 0101", "1011 0010 0101", "1101 1001 0010", "1110 1100 1001", "0110 1101 0010", "1010 1110 1001",
    175                            0x0729,           0x0762,           0x0BA9,           0x05B2,           0x0AB5,           0x0555,           0x0B25,           0x0D92,           0x0EC9,           0x06D2,           0x0AE9,
    176    //* 1542 -1552 */ "0101 0110 1011", "0100 1010 1011", "1010 0101 0101", "1101 0010 1001", "1101 0101 0100", "1101 1010 1010", "1001 1011 0101", "0100 1011 1010", "1010 0011 1011", "0100 1001 1011", "1010 0100 1101",
    177                            0x056B,           0x04AB,           0x0A55,           0x0D29,           0x0D54,           0x0DAA,           0x09B5,           0x04BA,           0x0A3B,           0x049B,           0x0A4D,
    178    //* 1553 -1563 */ "1010 1010 1010", "1010 1101 0101", "0010 1101 1010", "1001 0101 1101", "0100 0101 1110", "1010 0010 1110", "1100 1001 1010", "1101 0101 0101", "0110 1011 0010", "0110 1011 1001", "0100 1011 1010",
    179                            0x0AAA,           0x0AD5,           0x02DA,           0x095D,           0x045E,           0x0A2E,           0x0C9A,           0x0D55,           0x06B2,           0x06B9,           0x04BA,
    180    //* 1564 -1574 */ "1010 0101 1101", "0101 0010 1101", "1010 1001 0101", "1011 0101 0010", "1011 1010 1000", "1011 1011 0100", "0101 1011 1001", "0010 1101 1010", "1001 0101 1010", "1011 0100 1010", "1101 1010 0100",
    181                            0x0A5D,           0x052D,           0x0A95,           0x0B52,           0x0BA8,           0x0BB4,           0x05B9,           0x02DA,           0x095A,           0x0B4A,           0x0DA4,
    182    //* 1575 -1585 */ "1110 1101 0001", "0110 1110 1000", "1011 0110 1010", "0101 0110 1101", "0101 0011 0101", "0110 1001 0101", "1101 0100 1010", "1101 1010 1000", "1101 1101 0100", "0110 1101 1010", "0101 0101 1011",
    183                            0x0ED1,           0x06E8,           0x0B6A,           0x056D,           0x0535,           0x0695,           0x0D4A,           0x0DA8,           0x0DD4,           0x06DA,           0x055B,
    184    //* 1586 -1596 */ "0010 1001 1101", "0110 0010 1011", "1011 0001 0101", "1011 0100 1010", "1011 1001 0101", "0101 1010 1010", "1010 1010 1110", "1001 0010 1110", "1100 1000 1111", "0101 0010 0111", "0110 1001 0101",
    185                            0x029D,           0x062B,           0x0B15,           0x0B4A,           0x0B95,           0x05AA,           0x0AAE,           0x092E,           0x0C8F,           0x0527,           0x0695,
    186    //* 1597 -1600 */ "0110 1010 1010", "1010 1101 0110", "0101 0101 1101", "0010 1001 1101", };
    187                            0x06AA,           0x0AD6,           0x055D,           0x029D
    188 };
    189 
    190 //-------------------------------------------------------------------------
    191 // Constructors...
    192 //-------------------------------------------------------------------------
    193 
    194 const char *IslamicCalendar::getType() const {
    195    return "islamic";
    196 }
    197 
    198 IslamicCalendar* IslamicCalendar::clone() const {
    199    return new IslamicCalendar(*this);
    200 }
    201 
    202 IslamicCalendar::IslamicCalendar(const Locale& aLocale, UErrorCode& success)
    203 :   Calendar(TimeZone::forLocaleOrDefault(aLocale), aLocale, success)
    204 {
    205 }
    206 
    207 IslamicCalendar::~IslamicCalendar()
    208 {
    209 }
    210 //-------------------------------------------------------------------------
    211 // Minimum / Maximum access functions
    212 //-------------------------------------------------------------------------
    213 
    214 // Note: Current IslamicCalendar implementation does not work
    215 // well with negative years.
    216 
    217 // TODO: In some cases the current ICU Islamic calendar implementation shows
    218 // a month as having 31 days. Since date parsing now uses range checks based
    219 // on the table below, we need to change the range for last day of month to
    220 // include 31 as a workaround until the implementation is fixed.
    221 static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = {
    222    // Minimum  Greatest    Least  Maximum
    223    //           Minimum  Maximum
    224    {        0,        0,        0,        0}, // ERA
    225    {        1,        1,  5000000,  5000000}, // YEAR
    226    {        0,        0,       11,       11}, // MONTH
    227    {        1,        1,       50,       51}, // WEEK_OF_YEAR
    228    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // WEEK_OF_MONTH
    229    {        1,        1,       29,       31}, // DAY_OF_MONTH - 31 to workaround for cal implementation bug, should be 30
    230    {        1,        1,      354,      355}, // DAY_OF_YEAR
    231    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK
    232    {       -1,       -1,        5,        5}, // DAY_OF_WEEK_IN_MONTH
    233    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM
    234    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR
    235    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY
    236    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE
    237    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND
    238    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND
    239    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET
    240    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET
    241    {        1,        1,  5000000,  5000000}, // YEAR_WOY
    242    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL
    243    {        1,        1,  5000000,  5000000}, // EXTENDED_YEAR
    244    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
    245    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY
    246    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // IS_LEAP_MONTH
    247    {        0,        0,       11,       11}, // ORDINAL_MONTH
    248 };
    249 
    250 /**
    251 * @draft ICU 2.4
    252 */
    253 int32_t IslamicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const {
    254    return LIMITS[field][limitType];
    255 }
    256 
    257 //-------------------------------------------------------------------------
    258 // Assorted calculation utilities
    259 //
    260 
    261 namespace {
    262 
    263 // we could compress this down more if we need to
    264 static const int8_t umAlQuraYrStartEstimateFix[] = {
    265     0,  0, -1,  0, -1,  0,  0,  0,  0,  0, // 1300..
    266    -1,  0,  0,  0,  0,  0,  0,  0, -1,  0, // 1310..
    267     1,  0,  1,  1,  0,  0,  0,  0,  1,  0, // 1320..
    268     0,  0,  0,  0,  0,  0,  1,  0,  0,  0, // 1330..
    269     0,  0,  1,  0,  0, -1, -1,  0,  0,  0, // 1340..
    270     1,  0,  0, -1,  0,  0,  0,  1,  1,  0, // 1350..
    271     0,  0,  0,  0,  0,  0,  0, -1,  0,  0, // 1360..
    272     0,  1,  1,  0,  0, -1,  0,  1,  0,  1, // 1370..
    273     1,  0,  0, -1,  0,  1,  0,  0,  0, -1, // 1380..
    274     0,  1,  0,  1,  0,  0,  0, -1,  0,  0, // 1390..
    275     0,  0, -1, -1,  0, -1,  0,  1,  0,  0, // 1400..
    276     0, -1,  0,  0,  0,  1,  0,  0,  0,  0, // 1410..
    277     0,  1,  0,  0, -1, -1,  0,  0,  0,  1, // 1420..
    278     0,  0, -1, -1,  0, -1,  0,  0, -1, -1, // 1430..
    279     0, -1,  0, -1,  0,  0, -1, -1,  0,  0, // 1440..
    280     0,  0,  0,  0, -1,  0,  1,  0,  1,  1, // 1450..
    281     0,  0, -1,  0,  1,  0,  0,  0,  0,  0, // 1460..
    282     1,  0,  1,  0,  0,  0, -1,  0,  1,  0, // 1470..
    283     0, -1, -1,  0,  0,  0,  1,  0,  0,  0, // 1480..
    284     0,  0,  0,  0,  1,  0,  0,  0,  0,  0, // 1490..
    285     1,  0,  0, -1,  0,  0,  0,  1,  1,  0, // 1500..
    286     0, -1,  0,  1,  0,  1,  1,  0,  0,  0, // 1510..
    287     0,  1,  0,  0,  0, -1,  0,  0,  0,  1, // 1520..
    288     0,  0,  0, -1,  0,  0,  0,  0,  0, -1, // 1530..
    289     0, -1,  0,  1,  0,  0,  0, -1,  0,  1, // 1540..
    290     0,  1,  0,  0,  0,  0,  0,  1,  0,  0, // 1550..
    291    -1,  0,  0,  0,  0,  1,  0,  0,  0, -1, // 1560..
    292     0,  0,  0,  0, -1, -1,  0, -1,  0,  1, // 1570..
    293     0,  0, -1, -1,  0,  0,  1,  1,  0,  0, // 1580..
    294    -1,  0,  0,  0,  0,  1,  0,  0,  0,  0, // 1590..
    295     1 // 1600
    296 };
    297 
    298 /**
    299 * Determine whether a year is a leap year in the Islamic civil calendar
    300 */
    301 inline bool civilLeapYear(int32_t year) {
    302    return (14 + 11 * year) % 30 < 11;
    303 }
    304 
    305 int32_t trueMonthStart(int32_t month, UErrorCode& status);
    306 
    307 } // namespace
    308 
    309 /**
    310 * Return the day # on which the given year starts.  Days are counted
    311 * from the Hijri epoch, origin 0.
    312 */
    313 int64_t IslamicCalendar::yearStart(int32_t year, UErrorCode& status) const {
    314    return trueMonthStart(12*(year-1), status);
    315 }
    316 
    317 /**
    318 * Return the day # on which the given month starts.  Days are counted
    319 * from the Hijri epoch, origin 0.
    320 *
    321 * @param year  The hijri year
    322 * @param month The hijri month, 0-based (assumed to be in range 0..11)
    323 */
    324 int64_t IslamicCalendar::monthStart(int32_t year, int32_t month, UErrorCode& status) const {
    325    if (U_FAILURE(status)) {
    326        return 0;
    327    }
    328    int32_t temp;
    329    if (uprv_add32_overflow(year, -1, &temp) ||
    330        uprv_mul32_overflow(temp, 12, &temp) ||
    331        uprv_add32_overflow(temp, month, &month)) {
    332        status = U_ILLEGAL_ARGUMENT_ERROR;
    333        return 0;
    334    }
    335 
    336    return trueMonthStart(month, status);
    337 }
    338 
    339 namespace {
    340 /**
    341 * Return the "age" of the moon at the given time; this is the difference
    342 * in ecliptic latitude between the moon and the sun.  This method simply
    343 * calls CalendarAstronomer.moonAge, converts to degrees,
    344 * and adjusts the resultto be in the range [-180, 180].
    345 *
    346 * @param time  The time at which the moon's age is desired,
    347 *             in millis since 1/1/1970.
    348 */
    349 double moonAge(UDate time);
    350 
    351 /**
    352 * Find the day number on which a particular month of the true/lunar
    353 * Islamic calendar starts.
    354 *
    355 * @param month The month in question, origin 0 from the Hijri epoch
    356 *
    357 * @return The day number on which the given month starts.
    358 */
    359 int32_t trueMonthStart(int32_t month, UErrorCode& status) {
    360    if (U_FAILURE(status)) {
    361        return 0;
    362    }
    363    ucln_i18n_registerCleanup(UCLN_I18N_ISLAMIC_CALENDAR, calendar_islamic_cleanup);
    364    int64_t start = CalendarCache::get(&gMonthCache, month, status);
    365 
    366    if (U_SUCCESS(status) && start==0) {
    367        // Make a guess at when the month started, using the average length
    368        UDate origin = HIJRA_MILLIS 
    369            + uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH) * kOneDay;
    370 
    371        // moonAge will fail due to memory allocation error
    372        double age = moonAge(origin);
    373 
    374        if (age >= 0) {
    375            // The month has already started
    376            do {
    377                origin -= kOneDay;
    378                age = moonAge(origin);
    379            } while (age >= 0);
    380        }
    381        else {
    382            // Preceding month has not ended yet.
    383            do {
    384                origin += kOneDay;
    385                age = moonAge(origin);
    386            } while (age < 0);
    387        }
    388        start = ClockMath::floorDivideInt64(
    389            static_cast<int64_t>(static_cast<int64_t>(origin) - HIJRA_MILLIS), static_cast<int64_t>(kOneDay)) + 1;
    390        CalendarCache::put(&gMonthCache, month, start, status);
    391    }
    392    if(U_FAILURE(status)) {
    393        start = 0;
    394    }
    395    return start;
    396 }
    397 
    398 double moonAge(UDate time) {
    399    // Convert to degrees and normalize...
    400    double age = CalendarAstronomer(time).getMoonAge() * 180 / CalendarAstronomer::PI;
    401    if (age > 180) {
    402        age = age - 360;
    403    }
    404 
    405    return age;
    406 }
    407 
    408 }  // namespace
    409 //----------------------------------------------------------------------
    410 // Calendar framework
    411 //----------------------------------------------------------------------
    412 
    413 /**
    414 * Return the length (in days) of the given month.
    415 *
    416 * @param year  The hijri year
    417 * @param year  The hijri month, 0-based
    418 * @draft ICU 2.4
    419 */
    420 int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month,
    421                                              UErrorCode& status) const {
    422    month = 12*(extendedYear-1) + month;
    423    int32_t len = trueMonthStart(month+1, status) - trueMonthStart(month, status) ;
    424    if (U_FAILURE(status)) {
    425        return 0;
    426    }
    427    return len;
    428 }
    429 
    430 namespace {
    431 
    432 int32_t yearLength(int32_t extendedYear, UErrorCode& status) {
    433    int32_t month = 12*(extendedYear-1);
    434    int32_t length = trueMonthStart(month + 12, status) - trueMonthStart(month, status);
    435    if (U_FAILURE(status)) {
    436        return 0;
    437    }
    438    return length;
    439 }
    440 
    441 } // namepsace
    442 /**
    443 * Return the number of days in the given Islamic year
    444 * @draft ICU 2.4
    445 */
    446 int32_t IslamicCalendar::handleGetYearLength(int32_t extendedYear, UErrorCode& status) const {
    447    return yearLength(extendedYear, status);
    448 }
    449 
    450 //-------------------------------------------------------------------------
    451 // Functions for converting from field values to milliseconds....
    452 //-------------------------------------------------------------------------
    453 
    454 // Return JD of start of given month/year
    455 // Calendar says:
    456 // Get the Julian day of the day BEFORE the start of this year.
    457 // If useMonth is true, get the day before the start of the month.
    458 // Hence the -1
    459 /**
    460 * @draft ICU 2.4
    461 */
    462 int64_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
    463                                                 UBool /* useMonth */,
    464                                                 UErrorCode& status) const {
    465    if (U_FAILURE(status)) {
    466        return 0;
    467    }
    468    // This may be called by Calendar::handleComputeJulianDay with months out of the range
    469    // 0..11. Need to handle that here since monthStart requires months in the range 0.11.
    470    if (month > 11) {
    471        if (uprv_add32_overflow(eyear, (month / 12), &eyear)) {
    472            status = U_ILLEGAL_ARGUMENT_ERROR;
    473            return 0;
    474        }
    475        month %= 12;
    476    } else if (month < 0) {
    477        month++;
    478        if (uprv_add32_overflow(eyear, (month / 12) - 1, &eyear)) {
    479            status = U_ILLEGAL_ARGUMENT_ERROR;
    480            return 0;
    481        }
    482        month = (month % 12) + 11;
    483    }
    484    return monthStart(eyear, month, status) + getEpoc() - 1;
    485 }
    486 
    487 //-------------------------------------------------------------------------
    488 // Functions for converting from milliseconds to field values
    489 //-------------------------------------------------------------------------
    490 
    491 /**
    492 * @draft ICU 2.4
    493 */
    494 int32_t IslamicCalendar::handleGetExtendedYear(UErrorCode& /* status */) {
    495    if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
    496        return internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1
    497    }
    498    return internalGet(UCAL_YEAR, 1); // Default to year 1
    499 }
    500 
    501 /**
    502 * Override Calendar to compute several fields specific to the Islamic
    503 * calendar system.  These are:
    504 *
    505 * <ul><li>ERA
    506 * <li>YEAR
    507 * <li>MONTH
    508 * <li>DAY_OF_MONTH
    509 * <li>DAY_OF_YEAR
    510 * <li>EXTENDED_YEAR</ul>
    511 * 
    512 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
    513 * method is called. The getGregorianXxx() methods return Gregorian
    514 * calendar equivalents for the given Julian day.
    515 * @draft ICU 2.4
    516 */
    517 void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) {
    518    if (U_FAILURE(status)) {
    519        return;
    520    }
    521    int32_t days = julianDay - getEpoc();
    522 
    523    // Guess at the number of elapsed full months since the epoch
    524    int32_t month = static_cast<int32_t>(uprv_floor(static_cast<double>(days) / CalendarAstronomer::SYNODIC_MONTH));
    525 
    526    int32_t startDate = static_cast<int32_t>(uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH));
    527 
    528    double age = moonAge(internalGetTime());
    529    if ( days - startDate >= 25 && age > 0) {
    530        // If we're near the end of the month, assume next month and search backwards
    531        month++;
    532    }
    533 
    534    // Find out the last time that the new moon was actually visible at this longitude
    535    // This returns midnight the night that the moon was visible at sunset.
    536    while ((startDate = trueMonthStart(month, status)) > days) {
    537        if (U_FAILURE(status)) {
    538            return;
    539        }
    540        // If it was after the date in question, back up a month and try again
    541        month--;
    542    }
    543    if (U_FAILURE(status)) {
    544        return;
    545    }
    546 
    547    int32_t year = month >=  0 ? ((month / 12) + 1) : ((month + 1 ) / 12);
    548    month = ((month % 12) + 12 ) % 12;
    549    int64_t dayOfMonth = (days - monthStart(year, month, status)) + 1;
    550    if (U_FAILURE(status)) {
    551        return;
    552    }
    553    if (dayOfMonth > INT32_MAX || dayOfMonth < INT32_MIN) {
    554        status = U_ILLEGAL_ARGUMENT_ERROR;
    555        return;
    556    }
    557 
    558    // Now figure out the day of the year.
    559    int64_t dayOfYear = (days - monthStart(year, 0, status)) + 1;
    560    if (U_FAILURE(status)) {
    561        return;
    562    }
    563    if (dayOfYear > INT32_MAX || dayOfYear < INT32_MIN) {
    564        status = U_ILLEGAL_ARGUMENT_ERROR;
    565        return;
    566    }
    567 
    568    internalSet(UCAL_ERA, 0);
    569    internalSet(UCAL_YEAR, year);
    570    internalSet(UCAL_EXTENDED_YEAR, year);
    571    internalSet(UCAL_MONTH, month);
    572    internalSet(UCAL_ORDINAL_MONTH, month);
    573    internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
    574    internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
    575 }
    576 
    577 int32_t IslamicCalendar::getEpoc() const {
    578    return CIVIL_EPOC;
    579 }
    580 
    581 static int32_t gregoYearFromIslamicStart(int32_t year) {
    582    // ad hoc conversion, improve under #10752
    583    // rough est for now, ok for grego 1846-2138,
    584    // otherwise occasionally wrong (for 3% of years)
    585    int cycle, offset, shift = 0;
    586    if (year >= 1397) {
    587        cycle = (year - 1397) / 67;
    588        offset = (year - 1397) % 67;
    589        shift = 2*cycle + ((offset >= 33)? 1: 0);
    590    } else {
    591        cycle = (year - 1396) / 67 - 1;
    592        offset = -(year - 1396) % 67;
    593        shift = 2*cycle + ((offset <= 33)? 1: 0);
    594    }
    595    return year + 579 - shift;
    596 }
    597 
    598 int32_t IslamicCalendar::getRelatedYear(UErrorCode &status) const
    599 {
    600    int32_t year = get(UCAL_EXTENDED_YEAR, status);
    601    if (U_FAILURE(status)) {
    602        return 0;
    603    }
    604    return gregoYearFromIslamicStart(year);
    605 }
    606 
    607 void IslamicCalendar::setRelatedYear(int32_t year)
    608 {
    609    // ad hoc conversion, improve under #10752
    610    // rough est for now, ok for grego 1846-2138,
    611    // otherwise occasionally wrong (for 3% of years)
    612    int cycle, offset, shift = 0;
    613    if (year >= 1977) {
    614        cycle = (year - 1977) / 65;
    615        offset = (year - 1977) % 65;
    616        shift = 2*cycle + ((offset >= 32)? 1: 0);
    617    } else {
    618        cycle = (year - 1976) / 65 - 1;
    619        offset = -(year - 1976) % 65;
    620        shift = 2*cycle + ((offset <= 32)? 1: 0);
    621    }
    622    year = year - 579 + shift;
    623    set(UCAL_EXTENDED_YEAR, year);
    624 }
    625 
    626 IMPL_SYSTEM_DEFAULT_CENTURY(IslamicCalendar, "@calendar=islamic-civil")
    627 
    628 bool
    629 IslamicCalendar::inTemporalLeapYear(UErrorCode &status) const
    630 {
    631    int32_t days = getActualMaximum(UCAL_DAY_OF_YEAR, status);
    632    if (U_FAILURE(status)) {
    633        return false;
    634    }
    635    return days == 355;
    636 }
    637 
    638 /*****************************************************************************
    639 * IslamicCivilCalendar
    640 *****************************************************************************/
    641 IslamicCivilCalendar::IslamicCivilCalendar(const Locale& aLocale, UErrorCode& success)
    642    : IslamicCalendar(aLocale, success)
    643 {
    644 }
    645 
    646 IslamicCivilCalendar::~IslamicCivilCalendar()
    647 {
    648 }
    649 
    650 const char *IslamicCivilCalendar::getType() const {
    651    return "islamic-civil";
    652 }
    653 
    654 IslamicCivilCalendar* IslamicCivilCalendar::clone() const {
    655    return new IslamicCivilCalendar(*this);
    656 }
    657 
    658 /**
    659 * Return the day # on which the given year starts.  Days are counted
    660 * from the Hijri epoch, origin 0.
    661 */
    662 int64_t IslamicCivilCalendar::yearStart(int32_t year, UErrorCode& /* status */) const {
    663    return 354LL * (year-1LL) + ClockMath::floorDivideInt64(3 + 11LL * year, 30LL);
    664 }
    665 
    666 /**
    667 * Return the day # on which the given month starts.  Days are counted
    668 * from the Hijri epoch, origin 0.
    669 *
    670 * @param year  The hijri year
    671 * @param month The hijri month, 0-based (assumed to be in range 0..11)
    672 */
    673 int64_t IslamicCivilCalendar::monthStart(int32_t year, int32_t month, UErrorCode& /*status*/) const {
    674    // This does not handle months out of the range 0..11
    675    return static_cast<int64_t>(
    676        uprv_ceil(29.5*month) + 354LL*(year-1LL) +
    677        ClockMath::floorDivideInt64(
    678             11LL*static_cast<int64_t>(year) + 3LL, 30LL));
    679 }
    680 
    681 /**
    682 * Return the length (in days) of the given month.
    683 *
    684 * @param year  The hijri year
    685 * @param year  The hijri month, 0-based
    686 * @draft ICU 2.4
    687 */
    688 int32_t IslamicCivilCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month,
    689                                                   UErrorCode& /* status */) const {
    690    int32_t length = 29 + (month+1) % 2;
    691    if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
    692        length++;
    693    }
    694    return length;
    695 }
    696 
    697 /**
    698 * Return the number of days in the given Islamic year
    699 * @draft ICU 2.4
    700 */
    701 int32_t IslamicCivilCalendar::handleGetYearLength(int32_t extendedYear, UErrorCode& status) const {
    702    if (U_FAILURE(status)) return 0;
    703    return 354 + (civilLeapYear(extendedYear) ? 1 : 0);
    704 }
    705 
    706 /**
    707 * Override Calendar to compute several fields specific to the Islamic
    708 * calendar system.  These are:
    709 *
    710 * <ul><li>ERA
    711 * <li>YEAR
    712 * <li>MONTH
    713 * <li>DAY_OF_MONTH
    714 * <li>DAY_OF_YEAR
    715 * <li>EXTENDED_YEAR</ul>
    716 * 
    717 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
    718 * method is called. The getGregorianXxx() methods return Gregorian
    719 * calendar equivalents for the given Julian day.
    720 * @draft ICU 2.4
    721 */
    722 void IslamicCivilCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) {
    723    if (U_FAILURE(status)) {
    724        return;
    725    }
    726    int32_t days = julianDay - getEpoc();
    727 
    728    // Use the civil calendar approximation, which is just arithmetic
    729    int64_t year  =
    730        ClockMath::floorDivideInt64(30LL * days + 10646LL, 10631LL);
    731    int32_t month = static_cast<int32_t>(
    732        uprv_ceil((days - 29 - yearStart(year, status)) / 29.5 ));
    733    if (U_FAILURE(status)) {
    734        return;
    735    }
    736    month = month<11?month:11;
    737 
    738    int64_t dayOfMonth = (days - monthStart(year, month, status)) + 1;
    739    if (U_FAILURE(status)) {
    740        return;
    741    }
    742    if (dayOfMonth > INT32_MAX || dayOfMonth < INT32_MIN) {
    743        status = U_ILLEGAL_ARGUMENT_ERROR;
    744        return;
    745    }
    746 
    747    // Now figure out the day of the year.
    748    int64_t dayOfYear = (days - monthStart(year, 0, status)) + 1;
    749    if (U_FAILURE(status)) {
    750        return;
    751    }
    752    if (dayOfYear > INT32_MAX || dayOfYear < INT32_MIN) {
    753        status = U_ILLEGAL_ARGUMENT_ERROR;
    754        return;
    755    }
    756 
    757    internalSet(UCAL_ERA, 0);
    758    internalSet(UCAL_YEAR, year);
    759    internalSet(UCAL_EXTENDED_YEAR, year);
    760    internalSet(UCAL_MONTH, month);
    761    internalSet(UCAL_ORDINAL_MONTH, month);
    762    internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
    763    internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
    764 }
    765 /*****************************************************************************
    766 * IslamicTBLACalendar
    767 *****************************************************************************/
    768 IslamicTBLACalendar::IslamicTBLACalendar(const Locale& aLocale, UErrorCode& success)
    769    : IslamicCivilCalendar(aLocale, success)
    770 {
    771 }
    772 
    773 IslamicTBLACalendar::~IslamicTBLACalendar()
    774 {
    775 }
    776 
    777 const char *IslamicTBLACalendar::getType() const {
    778    return "islamic-tbla";
    779 }
    780 
    781 IslamicTBLACalendar* IslamicTBLACalendar::clone() const {
    782    return new IslamicTBLACalendar(*this);
    783 }
    784 
    785 int32_t IslamicTBLACalendar::getEpoc() const {
    786    return ASTRONOMICAL_EPOC;
    787 }
    788 
    789 /*****************************************************************************
    790 * IslamicUmalquraCalendar
    791 *****************************************************************************/
    792 IslamicUmalquraCalendar::IslamicUmalquraCalendar(const Locale& aLocale, UErrorCode& success)
    793    : IslamicCivilCalendar(aLocale, success)
    794 {
    795 }
    796 
    797 IslamicUmalquraCalendar::~IslamicUmalquraCalendar()
    798 {
    799 }
    800 
    801 const char *IslamicUmalquraCalendar::getType() const {
    802    return "islamic-umalqura";
    803 }
    804 
    805 IslamicUmalquraCalendar* IslamicUmalquraCalendar::clone() const {
    806    return new IslamicUmalquraCalendar(*this);
    807 }
    808 
    809 /**
    810 * Return the day # on which the given year starts.  Days are counted
    811 * from the Hijri epoch, origin 0.
    812 */
    813 int64_t IslamicUmalquraCalendar::yearStart(int32_t year, UErrorCode& status) const {
    814    if (year < UMALQURA_YEAR_START || year > UMALQURA_YEAR_END) {
    815        return IslamicCivilCalendar::yearStart(year, status);
    816    }
    817    year -= UMALQURA_YEAR_START;
    818    // rounded least-squares fit of the dates previously calculated from UMALQURA_MONTHLENGTH iteration
    819    int64_t yrStartLinearEstimate = static_cast<int64_t>(
    820        (354.36720 * static_cast<double>(year)) + 460322.05 + 0.5);
    821    // need a slight correction to some
    822    return yrStartLinearEstimate + umAlQuraYrStartEstimateFix[year];
    823 }
    824 
    825 /**
    826 * Return the day # on which the given month starts.  Days are counted
    827 * from the Hijri epoch, origin 0.
    828 *
    829 * @param year  The hijri year
    830 * @param month The hijri month, 0-based (assumed to be in range 0..11)
    831 */
    832 int64_t IslamicUmalquraCalendar::monthStart(int32_t year, int32_t month, UErrorCode& status) const {
    833    int64_t ms = yearStart(year, status);
    834    if (U_FAILURE(status)) {
    835        return 0;
    836    }
    837    for(int i=0; i< month; i++){
    838        ms+= handleGetMonthLength(year, i, status);
    839        if (U_FAILURE(status)) {
    840            return 0;
    841        }
    842    }
    843    return ms;
    844 }
    845 
    846 /**
    847 * Return the length (in days) of the given month.
    848 *
    849 * @param year  The hijri year
    850 * @param year  The hijri month, 0-based
    851 */
    852 int32_t IslamicUmalquraCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month,
    853                                                      UErrorCode& status) const {
    854    if (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END) {
    855        return IslamicCivilCalendar::handleGetMonthLength(extendedYear, month, status);
    856    }
    857    int32_t length = 29;
    858    int32_t mask = static_cast<int32_t>(0x01 << (11 - month)); // set mask for bit corresponding to month
    859    int32_t index = extendedYear - UMALQURA_YEAR_START;
    860    if ((UMALQURA_MONTHLENGTH[index] & mask) != 0) {
    861        length++;
    862    }
    863    return length;
    864 }
    865 
    866 int32_t IslamicUmalquraCalendar::yearLength(int32_t extendedYear, UErrorCode& status) const {
    867    if (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END) {
    868        return IslamicCivilCalendar::handleGetYearLength(extendedYear, status);
    869    }
    870    int length = 0;
    871    for(int i=0; i<12; i++) {
    872        length += handleGetMonthLength(extendedYear, i, status);
    873        if (U_FAILURE(status)) {
    874            return 0;
    875        }
    876    }
    877    return length;
    878 }
    879 
    880 /**
    881 * Return the number of days in the given Islamic year
    882 * @draft ICU 2.4
    883 */
    884 int32_t IslamicUmalquraCalendar::handleGetYearLength(int32_t extendedYear, UErrorCode& status) const {
    885    return yearLength(extendedYear, status);
    886 }
    887 
    888 /**
    889 * Override Calendar to compute several fields specific to the Islamic
    890 * calendar system.  These are:
    891 *
    892 * <ul><li>ERA
    893 * <li>YEAR
    894 * <li>MONTH
    895 * <li>DAY_OF_MONTH
    896 * <li>DAY_OF_YEAR
    897 * <li>EXTENDED_YEAR</ul>
    898 * 
    899 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
    900 * method is called. The getGregorianXxx() methods return Gregorian
    901 * calendar equivalents for the given Julian day.
    902 * @draft ICU 2.4
    903 */
    904 void IslamicUmalquraCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) {
    905    if (U_FAILURE(status)) {
    906        return;
    907    }
    908    int64_t year;
    909    int32_t month;
    910    int32_t days = julianDay - getEpoc();
    911 
    912    static int64_t kUmalquraStart = yearStart(UMALQURA_YEAR_START, status);
    913    if (U_FAILURE(status)) {
    914        return;
    915    }
    916    if (days < kUmalquraStart) {
    917        IslamicCivilCalendar::handleComputeFields(julianDay, status);
    918        return;
    919    }
    920    // Estimate a value y which is closer to but not greater than the year.
    921    // It is the inverse function of the logic inside
    922    // IslamicUmalquraCalendar::yearStart().
    923    year = ((static_cast<double>(days) - (460322.05 + 0.5)) / 354.36720) + UMALQURA_YEAR_START - 1;
    924    month = 0;
    925    int32_t d = 1;
    926    // need a slight correction to some
    927    while (d > 0) {
    928        d = days - yearStart(++year, status) + 1;
    929        int32_t length = yearLength(year, status);
    930        if (U_FAILURE(status)) {
    931            return;
    932        }
    933        if (d == length) {
    934            month = 11;
    935            break;
    936        }
    937        if (d < length){
    938            int32_t monthLen = handleGetMonthLength(year, month, status);
    939            for (month = 0;
    940                 d > monthLen;
    941                 monthLen = handleGetMonthLength(year, ++month, status)) {
    942                if (U_FAILURE(status)) {
    943                    return;
    944                }
    945                d -= monthLen;
    946            }
    947            break;
    948        }
    949    }
    950 
    951    int32_t dayOfMonth = monthStart(year, month, status);
    952    int32_t dayOfYear = monthStart(year, 0, status);
    953    if (U_FAILURE(status)) {
    954        return;
    955    }
    956    if (uprv_mul32_overflow(dayOfMonth, -1, &dayOfMonth) ||
    957        uprv_add32_overflow(dayOfMonth, days, &dayOfMonth) ||
    958        uprv_add32_overflow(dayOfMonth, 1, &dayOfMonth) ||
    959        // Now figure out the day of the year.
    960        uprv_mul32_overflow(dayOfYear, -1, &dayOfYear) ||
    961        uprv_add32_overflow(dayOfYear, days, &dayOfYear) ||
    962        uprv_add32_overflow(dayOfYear, 1, &dayOfYear)) {
    963        status = U_ILLEGAL_ARGUMENT_ERROR;
    964        return;
    965    }
    966 
    967    internalSet(UCAL_ERA, 0);
    968    internalSet(UCAL_YEAR, year);
    969    internalSet(UCAL_EXTENDED_YEAR, year);
    970    internalSet(UCAL_MONTH, month);
    971    internalSet(UCAL_ORDINAL_MONTH, month);
    972    internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
    973    internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
    974 }
    975 /*****************************************************************************
    976 * IslamicRGSACalendar
    977 *****************************************************************************/
    978 IslamicRGSACalendar::IslamicRGSACalendar(const Locale& aLocale, UErrorCode& success)
    979    : IslamicCalendar(aLocale, success)
    980 {
    981 }
    982 
    983 IslamicRGSACalendar::~IslamicRGSACalendar()
    984 {
    985 }
    986 
    987 const char *IslamicRGSACalendar::getType() const {
    988    return "islamic-rgsa";
    989 }
    990 
    991 IslamicRGSACalendar* IslamicRGSACalendar::clone() const {
    992    return new IslamicRGSACalendar(*this);
    993 }
    994 
    995 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar)
    996 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCivilCalendar)
    997 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicUmalquraCalendar)
    998 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicTBLACalendar)
    999 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicRGSACalendar)
   1000 
   1001 U_NAMESPACE_END
   1002 
   1003 #endif