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