From fbc1f33e7e8afeb92ed7498fca1a1686d8b6b9c4 Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Wed, 20 Mar 2024 13:39:06 -0700 Subject: [PATCH] ICU-22679 Clean up Calendar code. 1. Remove redudant implementation of default system ceuntry by using macro 2. Fold long if / else block if one block return. --- icu4c/source/i18n/buddhcal.cpp | 94 +++--------------------- icu4c/source/i18n/buddhcal.h | 21 +----- icu4c/source/i18n/cecal.cpp | 14 ++-- icu4c/source/i18n/cecal.h | 6 -- icu4c/source/i18n/chnsecal.cpp | 59 +-------------- icu4c/source/i18n/chnsecal.h | 30 +------- icu4c/source/i18n/coptccal.cpp | 66 ++++------------- icu4c/source/i18n/coptccal.h | 13 +--- icu4c/source/i18n/ethpccal.cpp | 42 +---------- icu4c/source/i18n/ethpccal.h | 13 +--- icu4c/source/i18n/gregocal.cpp | 77 +++++--------------- icu4c/source/i18n/gregoimp.h | 41 +++++++++++ icu4c/source/i18n/hebrwcal.cpp | 70 +++++------------- icu4c/source/i18n/hebrwcal.h | 19 +---- icu4c/source/i18n/indiancal.cpp | 55 +------------- icu4c/source/i18n/indiancal.h | 18 +---- icu4c/source/i18n/islamcal.cpp | 76 +++----------------- icu4c/source/i18n/islamcal.h | 26 +------ icu4c/source/i18n/japancal.cpp | 80 ++++++++++----------- icu4c/source/i18n/japancal.h | 17 +---- icu4c/source/i18n/persncal.cpp | 49 +------------ icu4c/source/i18n/persncal.h | 19 +---- icu4c/source/i18n/taiwncal.cpp | 103 +++++---------------------- icu4c/source/i18n/taiwncal.h | 19 +---- icu4c/source/i18n/unicode/calendar.h | 12 +++- icu4c/source/i18n/unicode/gregocal.h | 17 +---- 26 files changed, 198 insertions(+), 858 deletions(-) diff --git a/icu4c/source/i18n/buddhcal.cpp b/icu4c/source/i18n/buddhcal.cpp index 233184298d56..7723ade105d2 100644 --- a/icu4c/source/i18n/buddhcal.cpp +++ b/icu4c/source/i18n/buddhcal.cpp @@ -18,6 +18,7 @@ #if !UCONFIG_NO_FORMATTING #include "buddhcal.h" +#include "gregoimp.h" #include "unicode/gregocal.h" #include "umutex.h" #include @@ -70,16 +71,14 @@ int32_t BuddhistCalendar::handleGetExtendedYear(UErrorCode& status) } // EXTENDED_YEAR in BuddhistCalendar is a Gregorian year. // The default value of EXTENDED_YEAR is 1970 (Buddhist 2513) - int32_t year; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) { - year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); - } else { - // extended year is a gregorian year, where 1 = 1AD, 0 = 1BC, -1 = 2BC, etc - year = internalGet(UCAL_YEAR, kGregorianEpoch - kBuddhistEraStart); - if (uprv_add32_overflow(year, kBuddhistEraStart, &year)) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return 0; - } + return internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); + } + // extended year is a gregorian year, where 1 = 1AD, 0 = 1BC, -1 = 2BC, etc + int32_t year = internalGet(UCAL_YEAR, kGregorianEpoch - kBuddhistEraStart); + if (uprv_add32_overflow(year, kBuddhistEraStart, &year)) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; } return year; } @@ -96,84 +95,11 @@ int32_t BuddhistCalendar::handleGetLimit(UCalendarDateFields field, ELimitType l { if(field == UCAL_ERA) { return BE; - } else { - return GregorianCalendar::handleGetLimit(field,limitType); - } -} - -#if 0 -void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status) -{ - //Calendar::timeToFields(theTime, quick, status); - - int32_t era = internalGet(UCAL_ERA); - int32_t year = internalGet(UCAL_YEAR); - - if(era == GregorianCalendar::BC) { - year = 1-year; - era = BuddhistCalendar::BE; - } else if(era == GregorianCalendar::AD) { - era = BuddhistCalendar::BE; - } else { - status = U_INTERNAL_PROGRAM_ERROR; - } - - year = year - kBuddhistEraStart; - - internalSet(UCAL_ERA, era); - internalSet(UCAL_YEAR, year); -} -#endif - -/** - * The system maintains a static default century start date. This is initialized - * the first time it is used. Once the system default century date and year - * are set, they do not change. - */ -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gBCInitOnce {}; - - -UBool BuddhistCalendar::haveDefaultCentury() const -{ - return true; -} - -static void U_CALLCONV -initializeSystemDefaultCentury() -{ - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - UErrorCode status = U_ZERO_ERROR; - BuddhistCalendar calendar(Locale("@calendar=buddhist"),status); - if (U_SUCCESS(status)) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - UDate newStart = calendar.getTime(status); - int32_t newYear = calendar.get(UCAL_YEAR, status); - gSystemDefaultCenturyStartYear = newYear; - gSystemDefaultCenturyStart = newStart; } - // We have no recourse upon failure unless we want to propagate the failure - // out. -} - -UDate BuddhistCalendar::defaultCenturyStart() const -{ - // lazy-evaluate systemDefaultCenturyStart and systemDefaultCenturyStartYear - umtx_initOnce(gBCInitOnce, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t BuddhistCalendar::defaultCenturyStartYear() const -{ - // lazy-evaluate systemDefaultCenturyStartYear and systemDefaultCenturyStart - umtx_initOnce(gBCInitOnce, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; + return GregorianCalendar::handleGetLimit(field,limitType); } +IMPL_SYSTEM_DEFAULT_CENTURY(BuddhistCalendar, "@calendar=buddhist") U_NAMESPACE_END diff --git a/icu4c/source/i18n/buddhcal.h b/icu4c/source/i18n/buddhcal.h index a78ac6333434..1fa8395b35b2 100644 --- a/icu4c/source/i18n/buddhcal.h +++ b/icu4c/source/i18n/buddhcal.h @@ -159,26 +159,9 @@ class BuddhistCalendar : public GregorianCalendar { */ virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const override; - /** - * Returns true because the Buddhist Calendar does have a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; - virtual bool isEra0CountingBackward() const override { return false; } + + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY }; U_NAMESPACE_END diff --git a/icu4c/source/i18n/cecal.cpp b/icu4c/source/i18n/cecal.cpp index 628c883a4084..b550684b7988 100644 --- a/icu4c/source/i18n/cecal.cpp +++ b/icu4c/source/i18n/cecal.cpp @@ -105,12 +105,6 @@ CECalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) cons return LIMITS[field][limitType]; } -UBool -CECalendar::haveDefaultCentury() const -{ - return true; -} - //------------------------------------------------------------------------- // Calendar system Conversion methods... //------------------------------------------------------------------------- @@ -134,13 +128,17 @@ CECalendar::jdToCE(int32_t julianDay, int32_t jdEpochOffset, int32_t& year, int3 static const char* kMonthCode13 = "M13"; const char* CECalendar::getTemporalMonthCode(UErrorCode& status) const { - if (get(UCAL_MONTH, status) == 12) return kMonthCode13; + if (get(UCAL_MONTH, status) == 12) { + return kMonthCode13; + } return Calendar::getTemporalMonthCode(status); } void CECalendar::setTemporalMonthCode(const char* code, UErrorCode& status) { - if (U_FAILURE(status)) return; + if (U_FAILURE(status)) { + return; + } if (uprv_strcmp(code, kMonthCode13) == 0) { set(UCAL_MONTH, 12); set(UCAL_IS_LEAP_MONTH, 0); diff --git a/icu4c/source/i18n/cecal.h b/icu4c/source/i18n/cecal.h index ce0de467c27e..8f634e796357 100644 --- a/icu4c/source/i18n/cecal.h +++ b/icu4c/source/i18n/cecal.h @@ -106,12 +106,6 @@ class U_I18N_API CECalendar : public Calendar { */ virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const override; - /** - * Returns true because Coptic/Ethiopic Calendar does have a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - protected: /** * The Coptic and Ethiopic calendars differ only in their epochs. diff --git a/icu4c/source/i18n/chnsecal.cpp b/icu4c/source/i18n/chnsecal.cpp index 65886ba7088d..4154a39cc873 100644 --- a/icu4c/source/i18n/chnsecal.cpp +++ b/icu4c/source/i18n/chnsecal.cpp @@ -951,64 +951,7 @@ void ChineseCalendar::setRelatedYear(int32_t year) set(UCAL_EXTENDED_YEAR, year - kChineseRelatedYearDiff); } -// default century - -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInitOnce {}; - - -UBool ChineseCalendar::haveDefaultCentury() const -{ - return true; -} - -UDate ChineseCalendar::defaultCenturyStart() const -{ - return internalGetDefaultCenturyStart(); -} - -int32_t ChineseCalendar::defaultCenturyStartYear() const -{ - return internalGetDefaultCenturyStartYear(); -} - -namespace { // anonymous - -static void U_CALLCONV initializeSystemDefaultCentury() -{ - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - UErrorCode status = U_ZERO_ERROR; - ChineseCalendar calendar(Locale("@calendar=chinese"),status); - if (U_SUCCESS(status)) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - gSystemDefaultCenturyStart = calendar.getTime(status); - gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); - } - // We have no recourse upon failure unless we want to propagate the failure - // out. -} - -} // namespace - -UDate -ChineseCalendar::internalGetDefaultCenturyStart() const -{ - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInitOnce, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t -ChineseCalendar::internalGetDefaultCenturyStartYear() const -{ - // lazy-evaluate systemDefaultCenturyStartYear - umtx_initOnce(gSystemDefaultCenturyInitOnce, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} +IMPL_SYSTEM_DEFAULT_CENTURY(ChineseCalendar, "@calendar=chinese") bool ChineseCalendar::inTemporalLeapYear(UErrorCode &status) const diff --git a/icu4c/source/i18n/chnsecal.h b/icu4c/source/i18n/chnsecal.h index c7abefdf87c2..6c7d40af1733 100644 --- a/icu4c/source/i18n/chnsecal.h +++ b/icu4c/source/i18n/chnsecal.h @@ -279,39 +279,11 @@ class U_I18N_API ChineseCalendar : public Calendar { virtual int32_t internalGetMonth(UErrorCode& status) const override; protected: - /** - * Returns true because the Islamic Calendar does have a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY private: // default century stuff. - /** - * Returns the beginning date of the 100-year window that dates - * with 2-digit years are considered to fall within. - */ - UDate internalGetDefaultCenturyStart() const; - - /** - * Returns the first year of the 100-year window that dates with - * 2-digit years are considered to fall within. - */ - int32_t internalGetDefaultCenturyStartYear() const; - ChineseCalendar() = delete; // default constructor not implemented #ifdef __CalendarTest__ diff --git a/icu4c/source/i18n/coptccal.cpp b/icu4c/source/i18n/coptccal.cpp index 9bb502150066..343bcbc32934 100644 --- a/icu4c/source/i18n/coptccal.cpp +++ b/icu4c/source/i18n/coptccal.cpp @@ -11,6 +11,7 @@ #if !UCONFIG_NO_FORMATTING +#include "gregoimp.h" #include "umutex.h" #include "coptccal.h" #include "cecal.h" @@ -62,22 +63,19 @@ CopticCalendar::handleGetExtendedYear(UErrorCode& status) if (U_FAILURE(status)) { return 0; } - int32_t eyear; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) { - eyear = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 - } else { - // The year defaults to the epoch start, the era to CE - int32_t era = internalGet(UCAL_ERA, CE); - if (era == BCE) { - eyear = 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year - } else if (era == CE){ - eyear = internalGet(UCAL_YEAR, 1); // Default to year 1 - } else { - status = U_ILLEGAL_ARGUMENT_ERROR; - return 0; - } + return internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 + } + // The year defaults to the epoch start, the era to CE + int32_t era = internalGet(UCAL_ERA, CE); + if (era == BCE) { + return 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year } - return eyear; + if (era == CE){ + return internalGet(UCAL_YEAR, 1); // Default to year 1 + } + status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; } void @@ -120,45 +118,7 @@ void CopticCalendar::setRelatedYear(int32_t year) set(UCAL_EXTENDED_YEAR, year - kCopticRelatedYearDiff); } -/** - * The system maintains a static default century start date and Year. They are - * initialized the first time they are used. Once the system default century date - * and year are set, they do not change. - */ -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit {}; - - -static void U_CALLCONV initializeSystemDefaultCentury() { - UErrorCode status = U_ZERO_ERROR; - CopticCalendar calendar(Locale("@calendar=coptic"), status); - if (U_SUCCESS(status)) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - gSystemDefaultCenturyStart = calendar.getTime(status); - gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); - } - // We have no recourse upon failure unless we want to propagate the failure - // out. -} - -UDate -CopticCalendar::defaultCenturyStart() const -{ - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t -CopticCalendar::defaultCenturyStartYear() const -{ - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} - +IMPL_SYSTEM_DEFAULT_CENTURY(CopticCalendar, "@calendar=coptic") int32_t CopticCalendar::getJDEpochOffset() const diff --git a/icu4c/source/i18n/coptccal.h b/icu4c/source/i18n/coptccal.h index 377a045168d3..587bf37d0d14 100644 --- a/icu4c/source/i18n/coptccal.h +++ b/icu4c/source/i18n/coptccal.h @@ -185,18 +185,7 @@ class CopticCalendar : public CECalendar { */ virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY /** * Return the date offset from Julian diff --git a/icu4c/source/i18n/ethpccal.cpp b/icu4c/source/i18n/ethpccal.cpp index eca4819d0655..41b70767044d 100644 --- a/icu4c/source/i18n/ethpccal.cpp +++ b/icu4c/source/i18n/ethpccal.cpp @@ -11,6 +11,7 @@ #if !UCONFIG_NO_FORMATTING +#include "gregoimp.h" #include "umutex.h" #include "ethpccal.h" #include "cecal.h" @@ -110,46 +111,7 @@ void EthiopicCalendar::setRelatedYear(int32_t year) set(UCAL_EXTENDED_YEAR, year - kEthiopicRelatedYearDiff); } -/** - * The system maintains a static default century start date and Year. They are - * initialized the first time they are used. Once the system default century date - * and year are set, they do not change. - */ -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit {}; - -static void U_CALLCONV initializeSystemDefaultCentury() -{ - UErrorCode status = U_ZERO_ERROR; - EthiopicCalendar calendar(Locale("@calendar=ethiopic"), status); - if (U_SUCCESS(status)) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - - gSystemDefaultCenturyStart = calendar.getTime(status); - gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); - } - // We have no recourse upon failure unless we want to propagate the failure - // out. -} - -UDate -EthiopicCalendar::defaultCenturyStart() const -{ - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t -EthiopicCalendar::defaultCenturyStartYear() const -{ - // lazy-evaluate systemDefaultCenturyStartYear - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} - +IMPL_SYSTEM_DEFAULT_CENTURY(EthiopicCalendar, "@calendar=ethiopic") int32_t EthiopicCalendar::getJDEpochOffset() const diff --git a/icu4c/source/i18n/ethpccal.h b/icu4c/source/i18n/ethpccal.h index b6597c1d603d..36a3561186cb 100644 --- a/icu4c/source/i18n/ethpccal.h +++ b/icu4c/source/i18n/ethpccal.h @@ -177,18 +177,7 @@ class EthiopicCalendar : public CECalendar { */ virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY /** * Return the date offset from Julian diff --git a/icu4c/source/i18n/gregocal.cpp b/icu4c/source/i18n/gregocal.cpp index 3b2529a43dd7..dfd64faa50e7 100644 --- a/icu4c/source/i18n/gregocal.cpp +++ b/icu4c/source/i18n/gregocal.cpp @@ -355,23 +355,23 @@ GregorianCalendar::setGregorianChange(UDate date, UErrorCode& status) status = U_MEMORY_ALLOCATION_ERROR; return; } - if(U_FAILURE(status)) + if(U_FAILURE(status)) { return; + } cal->setTime(date, status); fGregorianCutoverYear = cal->get(UCAL_YEAR, status); - if (cal->get(UCAL_ERA, status) == BC) + if (cal->get(UCAL_ERA, status) == BC) { fGregorianCutoverYear = 1 - fGregorianCutoverYear; + } fCutoverJulianDay = (int32_t)cutoverDay; delete cal; } - void GregorianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) { int32_t eyear, month, dayOfMonth, dayOfYear, unusedRemainder; - - if(U_FAILURE(status)) { - return; + if(U_FAILURE(status)) { + return; } #if defined (U_DEBUG_CAL) @@ -379,7 +379,6 @@ void GregorianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& statu __FILE__, __LINE__, julianDay, getGregorianDayOfYear(), fCutoverJulianDay); #endif - if (julianDay >= fCutoverJulianDay) { month = getGregorianMonth(); dayOfMonth = getGregorianDayOfMonth(); @@ -776,7 +775,7 @@ double GregorianCalendar::computeJulianDayOfYear(UBool isGregorian, // ------------------------------------- -double +double GregorianCalendar::millisToJulianDay(UDate millis) { return (double)kEpochStartAsJulianDay + ClockMath::floorDivide(millis, (double)kOneDay); @@ -793,9 +792,9 @@ GregorianCalendar::julianDayToMillis(double julian) // ------------------------------------- int32_t -GregorianCalendar::aggregateStamp(int32_t stamp_a, int32_t stamp_b) +GregorianCalendar::aggregateStamp(int32_t stamp_a, int32_t stamp_b) { - return (((stamp_a != kUnset && stamp_b != kUnset) + return (((stamp_a != kUnset && stamp_b != kUnset) ? uprv_max(stamp_a, stamp_b) : (int32_t)kUnset)); } @@ -807,9 +806,9 @@ GregorianCalendar::aggregateStamp(int32_t stamp_a, int32_t stamp_b) * Note: This will be made public later. [LIU] */ -void +void GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status) { - roll((UCalendarDateFields) field, amount, status); + roll((UCalendarDateFields) field, amount, status); } void @@ -844,7 +843,7 @@ GregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& s if ((cMonthStart < fGregorianCutover) && (cMonthStart + (cMonthLen=(max-10))*kOneDay >= fGregorianCutover)) { inCutoverMonth = true; - } + } } break; default: @@ -908,7 +907,8 @@ GregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& s if( !inCutoverMonth ) { Calendar::roll(field, amount, status); return; - } else { + } + { // [j81] 1582 special case for DOM // The default computation works except when the current month // contains the Gregorian cutover. We handle this special case @@ -931,7 +931,8 @@ GregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& s if( !inCutoverMonth ) { Calendar::roll(field, amount, status); return; - } else { + } + { #if defined (U_DEBUG_CAL) fprintf(stderr, "%s:%d: roll WOM %d ??????????????????? \n", __FILE__, __LINE__,amount); @@ -1267,51 +1268,7 @@ GregorianCalendar::getType() const { return "gregorian"; } -/** - * The system maintains a static default century start date and Year. They are - * initialized the first time they are used. Once the system default century date - * and year are set, they do not change. - */ -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit {}; - - -UBool GregorianCalendar::haveDefaultCentury() const -{ - return true; -} - -static void U_CALLCONV -initializeSystemDefaultCentury() -{ - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - UErrorCode status = U_ZERO_ERROR; - GregorianCalendar calendar(status); - if (U_SUCCESS(status)) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - - gSystemDefaultCenturyStart = calendar.getTime(status); - gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); - } - // We have no recourse upon failure unless we want to propagate the failure - // out. -} - -UDate GregorianCalendar::defaultCenturyStart() const { - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t GregorianCalendar::defaultCenturyStartYear() const { - // lazy-evaluate systemDefaultCenturyStartYear - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} +IMPL_SYSTEM_DEFAULT_CENTURY(GregorianCalendar, "@calendar=gregory") U_NAMESPACE_END diff --git a/icu4c/source/i18n/gregoimp.h b/icu4c/source/i18n/gregoimp.h index a3e237d7eaf6..cd7694040d66 100644 --- a/icu4c/source/i18n/gregoimp.h +++ b/icu4c/source/i18n/gregoimp.h @@ -14,6 +14,7 @@ #ifndef GREGOIMP_H #define GREGOIMP_H #include "unicode/utypes.h" +#include "unicode/calendar.h" #if !UCONFIG_NO_FORMATTING #include "unicode/ures.h" @@ -322,6 +323,46 @@ inline int32_t Grego::gregorianShift(int32_t eyear) { return static_cast(gregShift); } +#define IMPL_SYSTEM_DEFAULT_CENTURY(T, U) \ + /** \ + * The system maintains a static default century start date and Year. They \ + * are initialized the first time they are used. Once the system default \ + * century date and year are set, they do not change \ + */ \ + namespace { \ + static UDate gSystemDefaultCenturyStart = DBL_MIN; \ + static int32_t gSystemDefaultCenturyStartYear = -1; \ + static icu::UInitOnce gSystemDefaultCenturyInit {}; \ + static void U_CALLCONV \ + initializeSystemDefaultCentury() { \ + UErrorCode status = U_ZERO_ERROR; \ + T calendar(U, status); \ + /* initialize systemDefaultCentury and systemDefaultCenturyYear based */ \ + /* on the current time. They'll be set to 80 years before */ \ + /* the current time. */ \ + if (U_FAILURE(status)) { \ + return; \ + } \ + calendar.setTime(Calendar::getNow(), status); \ + calendar.add(UCAL_YEAR, -80, status); \ + gSystemDefaultCenturyStart = calendar.getTime(status); \ + gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); \ + /* We have no recourse upon failure unless we want to propagate the */ \ + /* failure out. */ \ + } \ + } /* namespace */ \ + UDate T::defaultCenturyStart() const { \ + /* lazy-evaluate systemDefaultCenturyStart */ \ + umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); \ + return gSystemDefaultCenturyStart; \ + } \ + int32_t T::defaultCenturyStartYear() const { \ + /* lazy-evaluate systemDefaultCenturyStart */ \ + umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); \ + return gSystemDefaultCenturyStartYear; \ + } \ + UBool T::haveDefaultCentury() const { return true; } + U_NAMESPACE_END #endif // !UCONFIG_NO_FORMATTING diff --git a/icu4c/source/i18n/hebrwcal.cpp b/icu4c/source/i18n/hebrwcal.cpp index 17f4bdf72f56..d74ab2d3e7de 100644 --- a/icu4c/source/i18n/hebrwcal.cpp +++ b/icu4c/source/i18n/hebrwcal.cpp @@ -686,7 +686,7 @@ void HebrewCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) internalSet(UCAL_ORDINAL_MONTH, ordinal_month); internalSet(UCAL_MONTH, month); internalSet(UCAL_DAY_OF_MONTH, dayOfMonth); - internalSet(UCAL_DAY_OF_YEAR, dayOfYear); + internalSet(UCAL_DAY_OF_YEAR, dayOfYear); } //------------------------------------------------------------------------- @@ -700,13 +700,10 @@ int32_t HebrewCalendar::handleGetExtendedYear(UErrorCode& status ) { if (U_FAILURE(status)) { return 0; } - int32_t year; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) { - year = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 - } else { - year = internalGet(UCAL_YEAR, 1); // Default to year 1 + return internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 } - return year; + return internalGet(UCAL_YEAR, 1); // Default to year 1 } /** @@ -784,55 +781,16 @@ void HebrewCalendar::setRelatedYear(int32_t year) set(UCAL_EXTENDED_YEAR, year - kHebrewRelatedYearDiff); } -/** - * The system maintains a static default century start date and Year. They are - * initialized the first time they are used. Once the system default century date - * and year are set, they do not change. - */ -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit {}; - -UBool HebrewCalendar::haveDefaultCentury() const -{ - return true; -} - -static void U_CALLCONV initializeSystemDefaultCentury() -{ - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - UErrorCode status = U_ZERO_ERROR; - HebrewCalendar calendar(Locale("@calendar=hebrew"),status); - if (U_SUCCESS(status)) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - - gSystemDefaultCenturyStart = calendar.getTime(status); - gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); - } - // We have no recourse upon failure unless we want to propagate the failure - // out. -} - - -UDate HebrewCalendar::defaultCenturyStart() const { - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t HebrewCalendar::defaultCenturyStartYear() const { - // lazy-evaluate systemDefaultCenturyStartYear - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} +IMPL_SYSTEM_DEFAULT_CENTURY(HebrewCalendar, "@calendar=hebrew") bool HebrewCalendar::inTemporalLeapYear(UErrorCode& status) const { - if (U_FAILURE(status)) return false; + if (U_FAILURE(status)) { + return false; + } int32_t eyear = get(UCAL_EXTENDED_YEAR, status); - if (U_FAILURE(status)) return false; + if (U_FAILURE(status)) { + return false; + } return isLeapYear(eyear); } @@ -843,13 +801,17 @@ static const char * const gTemporalMonthCodesForHebrew[] = { const char* HebrewCalendar::getTemporalMonthCode(UErrorCode& status) const { int32_t month = get(UCAL_MONTH, status); - if (U_FAILURE(status)) return nullptr; + if (U_FAILURE(status)) { + return nullptr; + } return gTemporalMonthCodesForHebrew[month]; } void HebrewCalendar::setTemporalMonthCode(const char* code, UErrorCode& status ) { - if (U_FAILURE(status)) return; + if (U_FAILURE(status)) { + return; + } int32_t len = static_cast(uprv_strlen(code)); if (len == 3 || len == 4) { for (int m = 0; gTemporalMonthCodesForHebrew[m] != nullptr; m++) { diff --git a/icu4c/source/i18n/hebrwcal.h b/icu4c/source/i18n/hebrwcal.h index 69b377a0d6c3..342fdb0efa76 100644 --- a/icu4c/source/i18n/hebrwcal.h +++ b/icu4c/source/i18n/hebrwcal.h @@ -381,24 +381,7 @@ class U_I18N_API HebrewCalendar : public Calendar { virtual void validateField(UCalendarDateFields field, UErrorCode &status) override; protected: - /** - * Returns true because the Hebrew Calendar does have a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY public: /** diff --git a/icu4c/source/i18n/indiancal.cpp b/icu4c/source/i18n/indiancal.cpp index 7630aa425d51..1cca8e5f8412 100644 --- a/icu4c/source/i18n/indiancal.cpp +++ b/icu4c/source/i18n/indiancal.cpp @@ -329,60 +329,7 @@ void IndianCalendar::setRelatedYear(int32_t year) set(UCAL_EXTENDED_YEAR, year - kIndianRelatedYearDiff); } -/** - * The system maintains a static default century start date and Year. They are - * initialized the first time they are used. Once the system default century date - * and year are set, they do not change. - */ -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit {}; - - -UBool IndianCalendar::haveDefaultCentury() const -{ - return true; -} - -static void U_CALLCONV -initializeSystemDefaultCentury() -{ - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - UErrorCode status = U_ZERO_ERROR; - - IndianCalendar calendar ( Locale ( "@calendar=Indian" ), status); - if ( U_SUCCESS ( status ) ) { - calendar.setTime ( Calendar::getNow(), status ); - calendar.add ( UCAL_YEAR, -80, status ); - - UDate newStart = calendar.getTime ( status ); - int32_t newYear = calendar.get ( UCAL_YEAR, status ); - - gSystemDefaultCenturyStart = newStart; - gSystemDefaultCenturyStartYear = newYear; - } - // We have no recourse upon failure. -} - - -UDate -IndianCalendar::defaultCenturyStart() const -{ - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t -IndianCalendar::defaultCenturyStartYear() const -{ - // lazy-evaluate systemDefaultCenturyStartYear - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} - +IMPL_SYSTEM_DEFAULT_CENTURY(IndianCalendar, "@calendar=indian") UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndianCalendar) diff --git a/icu4c/source/i18n/indiancal.h b/icu4c/source/i18n/indiancal.h index ee91fb309b4d..2062bcec9103 100644 --- a/icu4c/source/i18n/indiancal.h +++ b/icu4c/source/i18n/indiancal.h @@ -304,24 +304,8 @@ class U_I18N_API IndianCalendar : public Calendar { // Default century. protected: - /** - * Returns true because the Indian Calendar does have a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY }; U_NAMESPACE_END diff --git a/icu4c/source/i18n/islamcal.cpp b/icu4c/source/i18n/islamcal.cpp index 2228c1dae61b..d299358a5f1c 100644 --- a/icu4c/source/i18n/islamcal.cpp +++ b/icu4c/source/i18n/islamcal.cpp @@ -476,17 +476,11 @@ int64_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, /** * @draft ICU 2.4 */ -int32_t IslamicCalendar::handleGetExtendedYear(UErrorCode& status) { - if (U_FAILURE(status)) { - return 0; - } - int32_t year; +int32_t IslamicCalendar::handleGetExtendedYear(UErrorCode& /* status */) { if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) { - year = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 - } else { - year = internalGet(UCAL_YEAR, 1); // Default to year 1 + return internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 } - return year; + return internalGet(UCAL_YEAR, 1); // Default to year 1 } /** @@ -587,7 +581,8 @@ int32_t IslamicCalendar::getRelatedYear(UErrorCode &status) const return gregoYearFromIslamicStart(year); } -static int32_t firstIslamicStartYearFromGrego(int32_t year) { +void IslamicCalendar::setRelatedYear(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) @@ -601,69 +596,20 @@ static int32_t firstIslamicStartYearFromGrego(int32_t year) { offset = -(year - 1976) % 65; shift = 2*cycle + ((offset <= 32)? 1: 0); } - return year - 579 + shift; -} - -void IslamicCalendar::setRelatedYear(int32_t year) -{ - set(UCAL_EXTENDED_YEAR, firstIslamicStartYearFromGrego(year)); -} - -/** - * The system maintains a static default century start date and Year. They are - * initialized the first time they are used. Once the system default century date - * and year are set, they do not change. - */ -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit {}; - - -UBool IslamicCalendar::haveDefaultCentury() const -{ - return true; -} - -UDate IslamicCalendar::defaultCenturyStart() const -{ - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; + year = year - 579 + shift; + set(UCAL_EXTENDED_YEAR, year); } -int32_t IslamicCalendar::defaultCenturyStartYear() const -{ - // lazy-evaluate systemDefaultCenturyStartYear - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} +IMPL_SYSTEM_DEFAULT_CENTURY(IslamicCalendar, "@calendar=islamic-civil") 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() -{ - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - UErrorCode status = U_ZERO_ERROR; - IslamicCalendar calendar(Locale("@calendar=islamic-civil"),status); - if (U_SUCCESS(status)) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - - gSystemDefaultCenturyStart = calendar.getTime(status); - gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); + if (U_FAILURE(status)) { + return false; } - // We have no recourse upon failure unless we want to propagate the failure - // out. + return days == 355; } /***************************************************************************** diff --git a/icu4c/source/i18n/islamcal.h b/icu4c/source/i18n/islamcal.h index 091ddf81c5a2..1fb9ecd506cb 100644 --- a/icu4c/source/i18n/islamcal.h +++ b/icu4c/source/i18n/islamcal.h @@ -338,32 +338,8 @@ class U_I18N_API IslamicCalendar : public Calendar { // Default century. protected: - /** - * Returns true because the Islamic Calendar does have a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; - - private: - /** - * Initializes the 100-year window that dates with 2-digit years - * are considered to fall within so that its start date is 80 years - * before the current time. - */ - static void U_CALLCONV initializeSystemDefaultCentury(); + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY }; /* diff --git a/icu4c/source/i18n/japancal.cpp b/icu4c/source/i18n/japancal.cpp index a91d0eaec3db..7e69b97a3af4 100644 --- a/icu4c/source/i18n/japancal.cpp +++ b/icu4c/source/i18n/japancal.cpp @@ -180,12 +180,9 @@ int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t eyear, int32_t month) UErrorCode status = U_ZERO_ERROR; gJapaneseEraRules->getStartDate(era, eraStart, status); U_ASSERT(U_SUCCESS(status)); - if(eyear == eraStart[0]) { - if(month == eraStart[1] - 1) { - return eraStart[2]; - } + if (eyear == eraStart[0] && (month == eraStart[1] - 1)) { + return eraStart[2]; } - return day; } @@ -202,24 +199,22 @@ int32_t JapaneseCalendar::handleGetExtendedYear(UErrorCode& status) } // EXTENDED_YEAR in JapaneseCalendar is a Gregorian year // The default value of EXTENDED_YEAR is 1970 (Showa 45) - int32_t year; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR && newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) { - year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); - } else { - int32_t eraStartYear = gJapaneseEraRules->getStartYear(internalGet(UCAL_ERA, gCurrentEra), status); - if (U_FAILURE(status)) { - return 0; - } + return internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); + } + int32_t eraStartYear = gJapaneseEraRules->getStartYear(internalGet(UCAL_ERA, gCurrentEra), status); + if (U_FAILURE(status)) { + return 0; + } - // extended year is a gregorian year, where 1 = 1AD, 0 = 1BC, -1 = 2BC, etc - year = internalGet(UCAL_YEAR, 1); // pin to minimum of year 1 (first year) - // add gregorian starting year, subtract one because year starts at 1 - if (uprv_add32_overflow(year, eraStartYear - 1, &year)) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return 0; - } + // extended year is a gregorian year, where 1 = 1AD, 0 = 1BC, -1 = 2BC, etc + int32_t year = internalGet(UCAL_YEAR, 1); // pin to minimum of year 1 (first year) + // add gregorian starting year, subtract one because year starts at 1 + if (uprv_add32_overflow(year, eraStartYear - 1, &year)) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; } return year; } @@ -288,31 +283,30 @@ int32_t JapaneseCalendar::handleGetLimit(UCalendarDateFields field, ELimitType l } int32_t JapaneseCalendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const { - if (field == UCAL_YEAR) { - int32_t era = get(UCAL_ERA, status); - if (U_FAILURE(status)) { - return 0; // error case... any value - } - if (era == gJapaneseEraRules->getNumberOfEras() - 1) { // max known era, not gCurrentEra - // TODO: Investigate what value should be used here - revisit after 4.0. - return handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM); - } else { - int32_t nextEraStart[3] = { 0,0,0 }; - gJapaneseEraRules->getStartDate(era + 1, nextEraStart, status); - int32_t nextEraYear = nextEraStart[0]; - int32_t nextEraMonth = nextEraStart[1]; // 1-base - int32_t nextEraDate = nextEraStart[2]; - - int32_t eraStartYear = gJapaneseEraRules->getStartYear(era, status); - int32_t maxYear = nextEraYear - eraStartYear + 1; // 1-base - if (nextEraMonth == 1 && nextEraDate == 1) { - // Subtract 1, because the next era starts at Jan 1 - maxYear--; - } - return maxYear; - } + if (field != UCAL_YEAR) { + return GregorianCalendar::getActualMaximum(field, status); + } + int32_t era = get(UCAL_ERA, status); + if (U_FAILURE(status)) { + return 0; // error case... any value + } + if (era == gJapaneseEraRules->getNumberOfEras() - 1) { // max known era, not gCurrentEra + // TODO: Investigate what value should be used here - revisit after 4.0. + return handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM); + } + int32_t nextEraStart[3] = { 0,0,0 }; + gJapaneseEraRules->getStartDate(era + 1, nextEraStart, status); + int32_t nextEraYear = nextEraStart[0]; + int32_t nextEraMonth = nextEraStart[1]; // 1-base + int32_t nextEraDate = nextEraStart[2]; + + int32_t eraStartYear = gJapaneseEraRules->getStartYear(era, status); + int32_t maxYear = nextEraYear - eraStartYear + 1; // 1-base + if (nextEraMonth == 1 && nextEraDate == 1) { + // Subtract 1, because the next era starts at Jan 1 + maxYear--; } - return GregorianCalendar::getActualMaximum(field, status); + return maxYear; } U_NAMESPACE_END diff --git a/icu4c/source/i18n/japancal.h b/icu4c/source/i18n/japancal.h index ae48095e0919..bd2a2ca07550 100644 --- a/icu4c/source/i18n/japancal.h +++ b/icu4c/source/i18n/japancal.h @@ -166,22 +166,7 @@ class JapaneseCalendar : public GregorianCalendar { */ virtual const char * getType() const override; - /** - * @return false - no default century in Japanese - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * Not used - no default century. - * @internal - */ - virtual UDate defaultCenturyStart() const override; - /** - * Not used - no default century. - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY private: JapaneseCalendar(); // default constructor not implemented diff --git a/icu4c/source/i18n/persncal.cpp b/icu4c/source/i18n/persncal.cpp index 7af3f5f8af34..c97a32197aca 100644 --- a/icu4c/source/i18n/persncal.cpp +++ b/icu4c/source/i18n/persncal.cpp @@ -196,13 +196,10 @@ int32_t PersianCalendar::handleGetExtendedYear(UErrorCode& status) { if (U_FAILURE(status)) { return 0; } - int32_t year; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) { - year = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 - } else { - year = internalGet(UCAL_YEAR, 1); // Default to year 1 + return internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 } - return year; + return internalGet(UCAL_YEAR, 1); // Default to year 1 } /** @@ -278,50 +275,10 @@ void PersianCalendar::setRelatedYear(int32_t year) set(UCAL_EXTENDED_YEAR, year - kPersianRelatedYearDiff); } -// default century - -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit {}; - -UBool PersianCalendar::haveDefaultCentury() const -{ - return true; -} - -static void U_CALLCONV initializeSystemDefaultCentury() { - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - UErrorCode status = U_ZERO_ERROR; - PersianCalendar calendar(Locale("@calendar=persian"),status); - if (U_SUCCESS(status)) - { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - - gSystemDefaultCenturyStart = calendar.getTime(status); - gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); - } - // We have no recourse upon failure unless we want to propagate the failure - // out. -} - -UDate PersianCalendar::defaultCenturyStart() const { - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t PersianCalendar::defaultCenturyStartYear() const { - // lazy-evaluate systemDefaultCenturyStartYear - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} +IMPL_SYSTEM_DEFAULT_CENTURY(PersianCalendar, "@calendar=persian") UOBJECT_DEFINE_RTTI_IMPLEMENTATION(PersianCalendar) U_NAMESPACE_END #endif - diff --git a/icu4c/source/i18n/persncal.h b/icu4c/source/i18n/persncal.h index f538e82042e4..daf7508b702a 100644 --- a/icu4c/source/i18n/persncal.h +++ b/icu4c/source/i18n/persncal.h @@ -296,24 +296,7 @@ class PersianCalendar : public Calendar { PersianCalendar(); // default constructor not implemented protected: - /** - * Returns true because the Persian Calendar does have a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY }; U_NAMESPACE_END diff --git a/icu4c/source/i18n/taiwncal.cpp b/icu4c/source/i18n/taiwncal.cpp index 69872fccf6ae..e6ffd71ba308 100644 --- a/icu4c/source/i18n/taiwncal.cpp +++ b/icu4c/source/i18n/taiwncal.cpp @@ -20,6 +20,7 @@ #if !UCONFIG_NO_FORMATTING #include "taiwncal.h" +#include "gregoimp.h" #include "unicode/gregocal.h" #include "umutex.h" #include @@ -30,7 +31,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TaiwanCalendar) static const int32_t kTaiwanEraStart = 1911; // 1911 (Gregorian) -static const int32_t kGregorianEpoch = 1970; +static const int32_t kGregorianEpoch = 1970; TaiwanCalendar::TaiwanCalendar(const Locale& aLocale, UErrorCode& success) : GregorianCalendar(aLocale, success) @@ -71,30 +72,29 @@ int32_t TaiwanCalendar::handleGetExtendedYear(UErrorCode& status) // EXTENDED_YEAR in TaiwanCalendar is a Gregorian year // The default value of EXTENDED_YEAR is 1970 (Minguo 59) - int32_t year = kGregorianEpoch; - if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR && newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) { - year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); - } else { - int32_t era = internalGet(UCAL_ERA, MINGUO); - year = internalGet(UCAL_YEAR, 1); - if(era == MINGUO) { + return internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); + } + int32_t era = internalGet(UCAL_ERA, MINGUO); + int32_t year = internalGet(UCAL_YEAR, 1); + switch (era) { + case MINGUO: if (uprv_add32_overflow(year, kTaiwanEraStart, &year)) { status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } - } else if(era == BEFORE_MINGUO) { + return year; + case BEFORE_MINGUO: if (uprv_add32_overflow(1 + kTaiwanEraStart, -year, &year)) { status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } - } else { + return year; + default: status = U_ILLEGAL_ARGUMENT_ERROR; return 0; - } } - return year; } void TaiwanCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) @@ -112,85 +112,16 @@ void TaiwanCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) int32_t TaiwanCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const { - if(field == UCAL_ERA) { - if(limitType == UCAL_LIMIT_MINIMUM || limitType == UCAL_LIMIT_GREATEST_MINIMUM) { - return BEFORE_MINGUO; - } else { - return MINGUO; - } - } else { + if(field != UCAL_ERA) { return GregorianCalendar::handleGetLimit(field,limitType); } -} - -#if 0 -void TaiwanCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status) -{ - //Calendar::timeToFields(theTime, quick, status); - - int32_t era = internalGet(UCAL_ERA); - int32_t year = internalGet(UCAL_YEAR); - - if(era == GregorianCalendar::BC) { - year = 1-year; - era = TaiwanCalendar::MINGUO; - } else if(era == GregorianCalendar::AD) { - era = TaiwanCalendar::MINGUO; - } else { - status = U_INTERNAL_PROGRAM_ERROR; + if (limitType == UCAL_LIMIT_MINIMUM || limitType == UCAL_LIMIT_GREATEST_MINIMUM) { + return BEFORE_MINGUO; } - - year = year - kTaiwanEraStart; - - internalSet(UCAL_ERA, era); - internalSet(UCAL_YEAR, year); + return MINGUO; } -#endif -/** - * The system maintains a static default century start date and Year. They are - * initialized the first time they are used. Once the system default century date - * and year are set, they do not change. - */ -static UDate gSystemDefaultCenturyStart = DBL_MIN; -static int32_t gSystemDefaultCenturyStartYear = -1; -static icu::UInitOnce gSystemDefaultCenturyInit {}; - -UBool TaiwanCalendar::haveDefaultCentury() const -{ - return true; -} - -static void U_CALLCONV initializeSystemDefaultCentury() -{ - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - UErrorCode status = U_ZERO_ERROR; - TaiwanCalendar calendar(Locale("@calendar=roc"),status); - if (U_SUCCESS(status)) - { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - - gSystemDefaultCenturyStart = calendar.getTime(status); - gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status); - } - // We have no recourse upon failure unless we want to propagate the failure - // out. -} - -UDate TaiwanCalendar::defaultCenturyStart() const { - // lazy-evaluate systemDefaultCenturyStart - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStart; -} - -int32_t TaiwanCalendar::defaultCenturyStartYear() const { - // lazy-evaluate systemDefaultCenturyStartYear - umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); - return gSystemDefaultCenturyStartYear; -} +IMPL_SYSTEM_DEFAULT_CENTURY(TaiwanCalendar, "@calendar=roc") U_NAMESPACE_END diff --git a/icu4c/source/i18n/taiwncal.h b/icu4c/source/i18n/taiwncal.h index c41227e322ed..a8fa3d1829ed 100644 --- a/icu4c/source/i18n/taiwncal.h +++ b/icu4c/source/i18n/taiwncal.h @@ -155,24 +155,7 @@ class TaiwanCalendar : public GregorianCalendar { */ virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const override; - /** - * Returns true because the Taiwan Calendar does have a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * Returns the date of the start of the default century - * @return start of century - in milliseconds since epoch, 1970 - * @internal - */ - virtual UDate defaultCenturyStart() const override; - - /** - * Returns the year in which the default century begins - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY }; U_NAMESPACE_END diff --git a/icu4c/source/i18n/unicode/calendar.h b/icu4c/source/i18n/unicode/calendar.h index 22ccf2e6e13d..171f3f64cea8 100644 --- a/icu4c/source/i18n/unicode/calendar.h +++ b/icu4c/source/i18n/unicode/calendar.h @@ -2564,8 +2564,18 @@ Calendar::internalSet(UCalendarDateFields field, int32_t value) fIsSet[field] = true; // Remove later } - #ifndef U_HIDE_INTERNAL_API +/** + * Macro for the class to declare it override + * haveDefaultCentury, defaultCenturyStart, and + * defaultCenturyStartYear functions in this class. + * @internal + */ +#define DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY \ + virtual UBool haveDefaultCentury() const override; \ + virtual UDate defaultCenturyStart() const override; \ + virtual int32_t defaultCenturyStartYear() const override; + inline int32_t Calendar::weekNumber(int32_t dayOfPeriod, int32_t dayOfWeek) { return weekNumber(dayOfPeriod, dayOfPeriod, dayOfWeek); diff --git a/icu4c/source/i18n/unicode/gregocal.h b/icu4c/source/i18n/unicode/gregocal.h index df5c987ab032..5112548522d5 100644 --- a/icu4c/source/i18n/unicode/gregocal.h +++ b/icu4c/source/i18n/unicode/gregocal.h @@ -722,23 +722,8 @@ class U_I18N_API GregorianCalendar: public Calendar { public: // internal implementation - /** - * @return true if this calendar has the notion of a default century - * @internal - */ - virtual UBool haveDefaultCentury() const override; - - /** - * @return the start of the default century - * @internal - */ - virtual UDate defaultCenturyStart() const override; + DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY - /** - * @return the beginning year of the default century - * @internal - */ - virtual int32_t defaultCenturyStartYear() const override; }; U_NAMESPACE_END