diff options
author | romankoshelev <romankoshelev@yandex-team.com> | 2023-08-14 19:51:50 +0300 |
---|---|---|
committer | romankoshelev <romankoshelev@yandex-team.com> | 2023-08-15 01:24:11 +0300 |
commit | cfcd865e05c0d0525ea27d1e153a043b32a85138 (patch) | |
tree | 68d3b3b25271e8a4998505897a269ff7ce119b76 /contrib/libs/icu/i18n/islamcal.cpp | |
parent | ccb790c507bd5e8ffe2ef9886ce5ee0a7ce22a15 (diff) | |
download | ydb-cfcd865e05c0d0525ea27d1e153a043b32a85138.tar.gz |
Update ICU to 73.2
Diffstat (limited to 'contrib/libs/icu/i18n/islamcal.cpp')
-rw-r--r-- | contrib/libs/icu/i18n/islamcal.cpp | 607 |
1 files changed, 411 insertions, 196 deletions
diff --git a/contrib/libs/icu/i18n/islamcal.cpp b/contrib/libs/icu/i18n/islamcal.cpp index de37e6b939..c21530a736 100644 --- a/contrib/libs/icu/i18n/islamcal.cpp +++ b/contrib/libs/icu/i18n/islamcal.cpp @@ -54,20 +54,20 @@ static void debug_islamcal_msg(const char *pat, ...) // --- The cache -- // cache of months -static icu::CalendarCache *gMonthCache = NULL; -static icu::CalendarAstronomer *gIslamicCalendarAstro = NULL; +static icu::CalendarCache *gMonthCache = nullptr; +static icu::CalendarAstronomer *gIslamicCalendarAstro = nullptr; U_CDECL_BEGIN -static UBool calendar_islamic_cleanup(void) { +static UBool calendar_islamic_cleanup() { if (gMonthCache) { delete gMonthCache; - gMonthCache = NULL; + gMonthCache = nullptr; } if (gIslamicCalendarAstro) { delete gIslamicCalendarAstro; - gIslamicCalendarAstro = NULL; + gIslamicCalendarAstro = nullptr; } - return TRUE; + return true; } U_CDECL_END @@ -206,67 +206,22 @@ int32_t getUmalqura_MonthLength(int32_t y, int32_t m) { //------------------------------------------------------------------------- const char *IslamicCalendar::getType() const { - const char *sType = NULL; - - switch (cType) { - case CIVIL: - sType = "islamic-civil"; - break; - case ASTRONOMICAL: - sType = "islamic"; - break; - case TBLA: - sType = "islamic-tbla"; - break; - case UMALQURA: - sType = "islamic-umalqura"; - break; - default: - UPRV_UNREACHABLE_EXIT; // out of range - } - return sType; + return "islamic"; } IslamicCalendar* IslamicCalendar::clone() const { return new IslamicCalendar(*this); } -IslamicCalendar::IslamicCalendar(const Locale& aLocale, UErrorCode& success, ECalculationType type) -: Calendar(TimeZone::forLocaleOrDefault(aLocale), aLocale, success), -cType(type) +IslamicCalendar::IslamicCalendar(const Locale& aLocale, UErrorCode& success) +: Calendar(TimeZone::forLocaleOrDefault(aLocale), aLocale, success) { setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly. } -IslamicCalendar::IslamicCalendar(const IslamicCalendar& other) : Calendar(other), cType(other.cType) { -} - IslamicCalendar::~IslamicCalendar() { } - -void IslamicCalendar::setCalculationType(ECalculationType type, UErrorCode &status) -{ - if (cType != type) { - // The fields of the calendar will become invalid, because the calendar - // rules are different - UDate m = getTimeInMillis(status); - cType = type; - clear(); - setTimeInMillis(m, status); - } -} - -/** -* Returns <code>true</code> if this object is using the fixed-cycle civil -* calendar, or <code>false</code> if using the religious, astronomical -* calendar. -* @draft ICU 2.4 -*/ -UBool IslamicCalendar::isCivil() { - return (cType == CIVIL); -} - //------------------------------------------------------------------------- // Minimum / Maximum access functions //------------------------------------------------------------------------- @@ -304,6 +259,7 @@ static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = { {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // IS_LEAP_MONTH + { 0, 0, 11, 11}, // ORDINAL_MONTH }; /** @@ -365,19 +321,7 @@ UBool IslamicCalendar::civilLeapYear(int32_t year) * from the Hijri epoch, origin 0. */ int32_t IslamicCalendar::yearStart(int32_t year) const{ - if (cType == CIVIL || cType == TBLA || - (cType == UMALQURA && (year < UMALQURA_YEAR_START || year > UMALQURA_YEAR_END))) - { - return (year-1)*354 + ClockMath::floorDivide((3+11*(int64_t)year),(int64_t)30); - } else if(cType==ASTRONOMICAL){ - return trueMonthStart(12*(year-1)); - } else { - year -= UMALQURA_YEAR_START; - // rounded least-squares fit of the dates previously calculated from UMALQURA_MONTHLENGTH iteration - int32_t yrStartLinearEstimate = (int32_t)((354.36720 * (double)year) + 460322.05 + 0.5); - // need a slight correction to some - return yrStartLinearEstimate + umAlQuraYrStartEstimateFix[year]; - } + return trueMonthStart(12*(year-1)); } /** @@ -388,19 +332,7 @@ int32_t IslamicCalendar::yearStart(int32_t year) const{ * @param month The hijri month, 0-based (assumed to be in range 0..11) */ int32_t IslamicCalendar::monthStart(int32_t year, int32_t month) const { - if (cType == CIVIL || cType == TBLA) { - // This does not handle months out of the range 0..11 - return (int32_t)uprv_ceil(29.5*month) - + (year-1)*354 + (int32_t)ClockMath::floorDivide((3+11*(int64_t)year),(int64_t)30); - } else if(cType==ASTRONOMICAL){ - return trueMonthStart(12*(year-1) + month); - } else { - int32_t ms = yearStart(year); - for(int i=0; i< month; i++){ - ms+= handleGetMonthLength(year, i); - } - return ms; - } + return trueMonthStart(12*(year-1) + month); } /** @@ -473,9 +405,9 @@ double IslamicCalendar::moonAge(UDate time, UErrorCode &status) static UMutex astroLock; // pod bay door lock umtx_lock(&astroLock); - if(gIslamicCalendarAstro == NULL) { + if(gIslamicCalendarAstro == nullptr) { gIslamicCalendarAstro = new CalendarAstronomer(); - if (gIslamicCalendarAstro == NULL) { + if (gIslamicCalendarAstro == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return age; } @@ -506,22 +438,8 @@ double IslamicCalendar::moonAge(UDate time, UErrorCode &status) * @draft ICU 2.4 */ int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const { - - int32_t length = 0; - - if (cType == CIVIL || cType == TBLA || - (cType == UMALQURA && (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END)) ) { - length = 29 + (month+1) % 2; - if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) { - length++; - } - } else if(cType == ASTRONOMICAL){ - month = 12*(extendedYear-1) + month; - length = trueMonthStart(month+1) - trueMonthStart(month) ; - } else { - length = getUmalqura_MonthLength(extendedYear - UMALQURA_YEAR_START, month); - } - return length; + month = 12*(extendedYear-1) + month; + return trueMonthStart(month+1) - trueMonthStart(month) ; } /** @@ -529,19 +447,8 @@ int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t mont * @draft ICU 2.4 */ int32_t IslamicCalendar::handleGetYearLength(int32_t extendedYear) const { - if (cType == CIVIL || cType == TBLA || - (cType == UMALQURA && (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END)) ) { - return 354 + (civilLeapYear(extendedYear) ? 1 : 0); - } else if(cType == ASTRONOMICAL){ - int32_t month = 12*(extendedYear-1); - return (trueMonthStart(month + 12) - trueMonthStart(month)); - } else { - int len = 0; - for(int i=0; i<12; i++) { - len += handleGetMonthLength(extendedYear, i); - } - return len; - } + int32_t month = 12*(extendedYear-1); + return (trueMonthStart(month + 12) - trueMonthStart(month)); } //------------------------------------------------------------------------- @@ -567,8 +474,8 @@ int32_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, U eyear += (month / 12) - 1; month = (month % 12) + 11; } - return monthStart(eyear, month) + ((cType == TBLA)? ASTRONOMICAL_EPOC: CIVIL_EPOC) - 1; -} + return monthStart(eyear, month) + getEpoc() - 1; +} //------------------------------------------------------------------------- // Functions for converting from milliseconds to field values @@ -604,105 +511,97 @@ int32_t IslamicCalendar::handleGetExtendedYear() { * @draft ICU 2.4 */ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) { - int32_t year, month, dayOfMonth, dayOfYear; - int32_t startDate; - int32_t days = julianDay - CIVIL_EPOC; + if (U_FAILURE(status)) return; + int32_t days = julianDay - getEpoc(); - if (cType == CIVIL || cType == TBLA) { - if(cType == TBLA) { - days = julianDay - ASTRONOMICAL_EPOC; - } - // Use the civil calendar approximation, which is just arithmetic - year = (int32_t)ClockMath::floorDivide(30 * (int64_t)days + 10646, (int64_t)10631); - month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 ); - month = month<11?month:11; - startDate = monthStart(year, month); - } else if(cType == ASTRONOMICAL){ - // Guess at the number of elapsed full months since the epoch - int32_t months = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH); + // Guess at the number of elapsed full months since the epoch + int32_t month = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH); - startDate = (int32_t)uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH); + int32_t startDate = (int32_t)uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH); - double age = moonAge(internalGetTime(), status); - if (U_FAILURE(status)) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - if ( days - startDate >= 25 && age > 0) { - // If we're near the end of the month, assume next month and search backwards - months++; - } - - // Find out the last time that the new moon was actually visible at this longitude - // This returns midnight the night that the moon was visible at sunset. - while ((startDate = trueMonthStart(months)) > days) { - // If it was after the date in question, back up a month and try again - months--; - } + double age = moonAge(internalGetTime(), status); + if (U_FAILURE(status)) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + if ( days - startDate >= 25 && age > 0) { + // If we're near the end of the month, assume next month and search backwards + month++; + } - year = months >= 0 ? ((months / 12) + 1) : ((months + 1 ) / 12); - month = ((months % 12) + 12 ) % 12; - } else if(cType == UMALQURA) { - int32_t umalquraStartdays = yearStart(UMALQURA_YEAR_START) ; - if( days < umalquraStartdays){ - //Use Civil calculation - year = (int32_t)ClockMath::floorDivide( - (30 * (int64_t)days + 10646) , (int64_t)10631.0 ); - month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 ); - month = month<11?month:11; - startDate = monthStart(year, month); - }else{ - int y =UMALQURA_YEAR_START-1, m =0; - long d = 1; - while(d > 0){ - y++; - d = days - yearStart(y) +1; - if(d == handleGetYearLength(y)){ - m=11; - break; - }else if(d < handleGetYearLength(y) ){ - int monthLen = handleGetMonthLength(y, m); - m=0; - while(d > monthLen){ - d -= monthLen; - m++; - monthLen = handleGetMonthLength(y, m); - } - break; - } - } - year = y; - month = m; - } - } else { // invalid 'civil' - UPRV_UNREACHABLE_EXIT; // should not get here, out of range + // Find out the last time that the new moon was actually visible at this longitude + // This returns midnight the night that the moon was visible at sunset. + while ((startDate = trueMonthStart(month)) > days) { + // If it was after the date in question, back up a month and try again + month--; } - dayOfMonth = (days - monthStart(year, month)) + 1; + int32_t year = month >= 0 ? ((month / 12) + 1) : ((month + 1 ) / 12); + month = ((month % 12) + 12 ) % 12; + int32_t dayOfMonth = (days - monthStart(year, month)) + 1; // Now figure out the day of the year. - dayOfYear = (days - monthStart(year, 0)) + 1; - + int32_t dayOfYear = (days - monthStart(year, 0)) + 1; internalSet(UCAL_ERA, 0); internalSet(UCAL_YEAR, year); internalSet(UCAL_EXTENDED_YEAR, year); internalSet(UCAL_MONTH, month); + internalSet(UCAL_ORDINAL_MONTH, month); internalSet(UCAL_DAY_OF_MONTH, dayOfMonth); - internalSet(UCAL_DAY_OF_YEAR, dayOfYear); -} + internalSet(UCAL_DAY_OF_YEAR, dayOfYear); +} + +int32_t IslamicCalendar::getEpoc() const { + return CIVIL_EPOC; +} -UBool -IslamicCalendar::inDaylightTime(UErrorCode& status) const +static int32_t gregoYearFromIslamicStart(int32_t year) { + // ad hoc conversion, improve under #10752 + // rough est for now, ok for grego 1846-2138, + // otherwise occasionally wrong (for 3% of years) + int cycle, offset, shift = 0; + if (year >= 1397) { + cycle = (year - 1397) / 67; + offset = (year - 1397) % 67; + shift = 2*cycle + ((offset >= 33)? 1: 0); + } else { + cycle = (year - 1396) / 67 - 1; + offset = -(year - 1396) % 67; + shift = 2*cycle + ((offset <= 33)? 1: 0); + } + return year + 579 - shift; +} + +int32_t IslamicCalendar::getRelatedYear(UErrorCode &status) const { - // copied from GregorianCalendar - if (U_FAILURE(status) || !getTimeZone().useDaylightTime()) - return FALSE; + int32_t year = get(UCAL_EXTENDED_YEAR, status); + if (U_FAILURE(status)) { + return 0; + } + return gregoYearFromIslamicStart(year); +} - // Force an update of the state of the Calendar. - ((IslamicCalendar*)this)->complete(status); // cast away const +static int32_t firstIslamicStartYearFromGrego(int32_t year) { + // ad hoc conversion, improve under #10752 + // rough est for now, ok for grego 1846-2138, + // otherwise occasionally wrong (for 3% of years) + int cycle, offset, shift = 0; + if (year >= 1977) { + cycle = (year - 1977) / 65; + offset = (year - 1977) % 65; + shift = 2*cycle + ((offset >= 32)? 1: 0); + } else { + cycle = (year - 1976) / 65 - 1; + offset = -(year - 1976) % 65; + shift = 2*cycle + ((offset <= 32)? 1: 0); + } + return year - 579 + shift; +} - return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE); +void IslamicCalendar::setRelatedYear(int32_t year) +{ + set(UCAL_EXTENDED_YEAR, firstIslamicStartYearFromGrego(year)); } /** @@ -712,12 +611,12 @@ IslamicCalendar::inDaylightTime(UErrorCode& status) const */ static UDate gSystemDefaultCenturyStart = DBL_MIN; static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER; +static icu::UInitOnce gSystemDefaultCenturyInit {}; UBool IslamicCalendar::haveDefaultCentury() const { - return TRUE; + return true; } UDate IslamicCalendar::defaultCenturyStart() const @@ -734,6 +633,14 @@ int32_t IslamicCalendar::defaultCenturyStartYear() const return gSystemDefaultCenturyStartYear; } +bool +IslamicCalendar::inTemporalLeapYear(UErrorCode &status) const +{ + int32_t days = getActualMaximum(UCAL_DAY_OF_YEAR, status); + if (U_FAILURE(status)) return false; + return days == 355; +} + U_CFUNC void U_CALLCONV IslamicCalendar::initializeSystemDefaultCentury() @@ -754,9 +661,317 @@ IslamicCalendar::initializeSystemDefaultCentury() // out. } +/***************************************************************************** + * IslamicCivilCalendar + *****************************************************************************/ +IslamicCivilCalendar::IslamicCivilCalendar(const Locale& aLocale, UErrorCode& success) + : IslamicCalendar(aLocale, success) +{ +} + +IslamicCivilCalendar::~IslamicCivilCalendar() +{ +} + +const char *IslamicCivilCalendar::getType() const { + return "islamic-civil"; +} + +IslamicCivilCalendar* IslamicCivilCalendar::clone() const { + return new IslamicCivilCalendar(*this); +} + +/** +* Return the day # on which the given year starts. Days are counted +* from the Hijri epoch, origin 0. +*/ +int32_t IslamicCivilCalendar::yearStart(int32_t year) const{ + return static_cast<int32_t>( + (year-1)*354 + ClockMath::floorDivide((3+11*static_cast<int64_t>(year)), + static_cast<int64_t>(30))); +} + +/** +* Return the day # on which the given month starts. Days are counted +* from the Hijri epoch, origin 0. +* +* @param year The hijri year +* @param month The hijri month, 0-based (assumed to be in range 0..11) +*/ +int32_t IslamicCivilCalendar::monthStart(int32_t year, int32_t month) const { + // This does not handle months out of the range 0..11 + return static_cast<int32_t>( + uprv_ceil(29.5*month) + (year-1)*354 + + static_cast<int32_t>(ClockMath::floorDivide( + 3+11*static_cast<int64_t>(year), + static_cast<int64_t>(30)))); +} + +/** +* Return the length (in days) of the given month. +* +* @param year The hijri year +* @param year The hijri month, 0-based +* @draft ICU 2.4 +*/ +int32_t IslamicCivilCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const { + int32_t length = 29 + (month+1) % 2; + if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) { + length++; + } + return length; +} + +/** +* Return the number of days in the given Islamic year +* @draft ICU 2.4 +*/ +int32_t IslamicCivilCalendar::handleGetYearLength(int32_t extendedYear) const { + return 354 + (civilLeapYear(extendedYear) ? 1 : 0); +} + +/** +* Override Calendar to compute several fields specific to the Islamic +* calendar system. These are: +* +* <ul><li>ERA +* <li>YEAR +* <li>MONTH +* <li>DAY_OF_MONTH +* <li>DAY_OF_YEAR +* <li>EXTENDED_YEAR</ul> +* +* The DAY_OF_WEEK and DOW_LOCAL fields are already set when this +* method is called. The getGregorianXxx() methods return Gregorian +* calendar equivalents for the given Julian day. +* @draft ICU 2.4 +*/ +void IslamicCivilCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) { + if (U_FAILURE(status)) return; + int32_t days = julianDay - getEpoc(); + + // Use the civil calendar approximation, which is just arithmetic + int32_t year = static_cast<int32_t>( + ClockMath::floorDivide(30 * static_cast<int64_t>(days) + 10646, + static_cast<int64_t>(10631))); + int32_t month = static_cast<int32_t>( + uprv_ceil((days - 29 - yearStart(year)) / 29.5 )); + month = month<11?month:11; + + int32_t dayOfMonth = (days - monthStart(year, month)) + 1; + + // Now figure out the day of the year. + int32_t dayOfYear = (days - monthStart(year, 0)) + 1; + + internalSet(UCAL_ERA, 0); + internalSet(UCAL_YEAR, year); + internalSet(UCAL_EXTENDED_YEAR, year); + internalSet(UCAL_MONTH, month); + internalSet(UCAL_ORDINAL_MONTH, month); + internalSet(UCAL_DAY_OF_MONTH, dayOfMonth); + internalSet(UCAL_DAY_OF_YEAR, dayOfYear); +} +/***************************************************************************** + * IslamicTBLACalendar + *****************************************************************************/ +IslamicTBLACalendar::IslamicTBLACalendar(const Locale& aLocale, UErrorCode& success) + : IslamicCivilCalendar(aLocale, success) +{ +} + +IslamicTBLACalendar::~IslamicTBLACalendar() +{ +} + +const char *IslamicTBLACalendar::getType() const { + return "islamic-tbla"; +} + +IslamicTBLACalendar* IslamicTBLACalendar::clone() const { + return new IslamicTBLACalendar(*this); +} + +int32_t IslamicTBLACalendar::getEpoc() const { + return ASTRONOMICAL_EPOC; +} + +/***************************************************************************** + * IslamicUmalquraCalendar + *****************************************************************************/ +IslamicUmalquraCalendar::IslamicUmalquraCalendar(const Locale& aLocale, UErrorCode& success) + : IslamicCalendar(aLocale, success) +{ +} + +IslamicUmalquraCalendar::~IslamicUmalquraCalendar() +{ +} +const char *IslamicUmalquraCalendar::getType() const { + return "islamic-umalqura"; +} + +IslamicUmalquraCalendar* IslamicUmalquraCalendar::clone() const { + return new IslamicUmalquraCalendar(*this); +} + +/** +* Return the day # on which the given year starts. Days are counted +* from the Hijri epoch, origin 0. +*/ +int32_t IslamicUmalquraCalendar::yearStart(int32_t year) const { + if (year < UMALQURA_YEAR_START || year > UMALQURA_YEAR_END) { + return static_cast<int32_t>( + (year-1)*354 + ClockMath::floorDivide((3+11*static_cast<int64_t>(year)), + static_cast<int64_t>(30))); + } + year -= UMALQURA_YEAR_START; + // rounded least-squares fit of the dates previously calculated from UMALQURA_MONTHLENGTH iteration + int32_t yrStartLinearEstimate = static_cast<int32_t>( + (354.36720 * (double)year) + 460322.05 + 0.5); + // need a slight correction to some + return yrStartLinearEstimate + umAlQuraYrStartEstimateFix[year]; +} + +/** +* Return the day # on which the given month starts. Days are counted +* from the Hijri epoch, origin 0. +* +* @param year The hijri year +* @param month The hijri month, 0-based (assumed to be in range 0..11) +*/ +int32_t IslamicUmalquraCalendar::monthStart(int32_t year, int32_t month) const { + int32_t ms = yearStart(year); + for(int i=0; i< month; i++){ + ms+= handleGetMonthLength(year, i); + } + return ms; +} + +/** +* Return the length (in days) of the given month. +* +* @param year The hijri year +* @param year The hijri month, 0-based +*/ +int32_t IslamicUmalquraCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const { + int32_t length = 0; + if (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END) { + length = 29 + (month+1) % 2; + if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) { + length++; + } + return length; + } + return getUmalqura_MonthLength(extendedYear - UMALQURA_YEAR_START, month); +} + +/** +* Return the number of days in the given Islamic year +* @draft ICU 2.4 +*/ +int32_t IslamicUmalquraCalendar::handleGetYearLength(int32_t extendedYear) const { + if (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END) { + return 354 + (civilLeapYear(extendedYear) ? 1 : 0); + } + int len = 0; + for(int i=0; i<12; i++) { + len += handleGetMonthLength(extendedYear, i); + } + return len; +} + +/** +* Override Calendar to compute several fields specific to the Islamic +* calendar system. These are: +* +* <ul><li>ERA +* <li>YEAR +* <li>MONTH +* <li>DAY_OF_MONTH +* <li>DAY_OF_YEAR +* <li>EXTENDED_YEAR</ul> +* +* The DAY_OF_WEEK and DOW_LOCAL fields are already set when this +* method is called. The getGregorianXxx() methods return Gregorian +* calendar equivalents for the given Julian day. +* @draft ICU 2.4 +*/ +void IslamicUmalquraCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) { + if (U_FAILURE(status)) return; + int32_t year, month, dayOfMonth, dayOfYear; + int32_t days = julianDay - getEpoc(); + + int32_t umalquraStartdays = yearStart(UMALQURA_YEAR_START) ; + if (days < umalquraStartdays) { + //Use Civil calculation + year = (int32_t)ClockMath::floorDivide( + (30 * (int64_t)days + 10646) , (int64_t)10631.0 ); + month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 ); + month = month < 11 ? month : 11; + } else { + int y =UMALQURA_YEAR_START-1, m =0; + long d = 1; + while (d > 0) { + y++; + d = days - yearStart(y) +1; + if (d == handleGetYearLength(y)) { + m=11; + break; + } + if (d < handleGetYearLength(y)){ + int monthLen = handleGetMonthLength(y, m); + m=0; + while(d > monthLen){ + d -= monthLen; + m++; + monthLen = handleGetMonthLength(y, m); + } + break; + } + } + year = y; + month = m; + } + + dayOfMonth = (days - monthStart(year, month)) + 1; + + // Now figure out the day of the year. + dayOfYear = (days - monthStart(year, 0)) + 1; + + internalSet(UCAL_ERA, 0); + internalSet(UCAL_YEAR, year); + internalSet(UCAL_EXTENDED_YEAR, year); + internalSet(UCAL_MONTH, month); + internalSet(UCAL_ORDINAL_MONTH, month); + internalSet(UCAL_DAY_OF_MONTH, dayOfMonth); + internalSet(UCAL_DAY_OF_YEAR, dayOfYear); +} +/***************************************************************************** + * IslamicRGSACalendar + *****************************************************************************/ +IslamicRGSACalendar::IslamicRGSACalendar(const Locale& aLocale, UErrorCode& success) + : IslamicCalendar(aLocale, success) +{ +} + +IslamicRGSACalendar::~IslamicRGSACalendar() +{ +} + +const char *IslamicRGSACalendar::getType() const { + return "islamic-rgsa"; +} + +IslamicRGSACalendar* IslamicRGSACalendar::clone() const { + return new IslamicRGSACalendar(*this); +} UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar) +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCivilCalendar) +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicUmalquraCalendar) +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicTBLACalendar) +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicRGSACalendar) U_NAMESPACE_END |