]> granicus.if.org Git - icu/commitdiff
ICU-10752 Spread (s|g)etRelativeYear to subclass
authorFrank Tang <ftang@chromium.org>
Thu, 22 Sep 2022 04:11:38 +0000 (21:11 -0700)
committerFrank Yung-Fong Tang <ftang@google.com>
Wed, 9 Nov 2022 21:18:24 +0000 (13:18 -0800)
Remove the switch statment implementaiton in
Calendar::(g|s)etRelatedYear
and move the code into each subclass as proper OOP style.

17 files changed:
icu4c/source/i18n/calendar.cpp
icu4c/source/i18n/chnsecal.cpp
icu4c/source/i18n/chnsecal.h
icu4c/source/i18n/coptccal.cpp
icu4c/source/i18n/coptccal.h
icu4c/source/i18n/dangical.cpp
icu4c/source/i18n/dangical.h
icu4c/source/i18n/ethpccal.cpp
icu4c/source/i18n/ethpccal.h
icu4c/source/i18n/hebrwcal.cpp
icu4c/source/i18n/hebrwcal.h
icu4c/source/i18n/indiancal.cpp
icu4c/source/i18n/indiancal.h
icu4c/source/i18n/islamcal.cpp
icu4c/source/i18n/islamcal.h
icu4c/source/i18n/persncal.cpp
icu4c/source/i18n/persncal.h

index ffd84761becd008a0b520f704d4c043ca5a9d7ac..f5a40e48395a2cbaddb3384f74acb2fc326d4768 100644 (file)
@@ -1267,130 +1267,14 @@ Calendar::set(int32_t year, int32_t month, int32_t date, int32_t hour, int32_t m
 }
 
 // -------------------------------------
-// For now the full getRelatedYear implementation is here;
-// per #10752 move the non-default implementation to subclasses
-// (default implementation will do no year adjustment)
-
-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 Calendar::getRelatedYear(UErrorCode &status) const
 {
-    if (U_FAILURE(status)) {
-        return 0;
-    }
-    int32_t year = get(UCAL_EXTENDED_YEAR, status);
-    if (U_FAILURE(status)) {
-        return 0;
-    }
-    // modify for calendar type
-    ECalType type = getCalendarType(getType());
-    switch (type) {
-        case CALTYPE_PERSIAN:
-            year += 622; break;
-        case CALTYPE_HEBREW:
-            year -= 3760; break;
-        case CALTYPE_CHINESE:
-            year -= 2637; break;
-        case CALTYPE_INDIAN:
-            year += 79; break;
-        case CALTYPE_COPTIC:
-            year += 284; break;
-        case CALTYPE_ETHIOPIC:
-            year += 8; break;
-        case CALTYPE_ETHIOPIC_AMETE_ALEM:
-            year -=5492; break;
-        case CALTYPE_DANGI:
-            year -= 2333; break;
-        case CALTYPE_ISLAMIC_CIVIL:
-        case CALTYPE_ISLAMIC:
-        case CALTYPE_ISLAMIC_UMALQURA:
-        case CALTYPE_ISLAMIC_TBLA:
-        case CALTYPE_ISLAMIC_RGSA:
-            year = gregoYearFromIslamicStart(year); break;
-        default:
-            // CALTYPE_GREGORIAN
-            // CALTYPE_JAPANESE
-            // CALTYPE_BUDDHIST
-            // CALTYPE_ROC
-            // CALTYPE_ISO8601
-            // do nothing, EXTENDED_YEAR same as Gregorian
-            break;
-    }
-    return year;
+    return get(UCAL_EXTENDED_YEAR, status);
 }
 
 // -------------------------------------
-// For now the full setRelatedYear implementation is here;
-// per #10752 move the non-default implementation to subclasses
-// (default implementation will do no year adjustment)
-
-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;
-}
 void Calendar::setRelatedYear(int32_t year)
 {
-    // modify for calendar type
-    ECalType type = getCalendarType(getType());
-    switch (type) {
-        case CALTYPE_PERSIAN:
-            year -= 622; break;
-        case CALTYPE_HEBREW:
-            year += 3760; break;
-        case CALTYPE_CHINESE:
-            year += 2637; break;
-        case CALTYPE_INDIAN:
-            year -= 79; break;
-        case CALTYPE_COPTIC:
-            year -= 284; break;
-        case CALTYPE_ETHIOPIC:
-            year -= 8; break;
-        case CALTYPE_ETHIOPIC_AMETE_ALEM:
-            year +=5492; break;
-        case CALTYPE_DANGI:
-            year += 2333; break;
-        case CALTYPE_ISLAMIC_CIVIL:
-        case CALTYPE_ISLAMIC:
-        case CALTYPE_ISLAMIC_UMALQURA:
-        case CALTYPE_ISLAMIC_TBLA:
-        case CALTYPE_ISLAMIC_RGSA:
-            year = firstIslamicStartYearFromGrego(year); break;
-        default:
-            // CALTYPE_GREGORIAN
-            // CALTYPE_JAPANESE
-            // CALTYPE_BUDDHIST
-            // CALTYPE_ROC
-            // CALTYPE_ISO8601
-            // do nothing, EXTENDED_YEAR same as Gregorian
-            break;
-    }
     // set extended year
     set(UCAL_EXTENDED_YEAR, year);
 }
index b2b6258820b7ddfd3c3b73bd1b3ade66930b13dc..c1e131247cbe2d71009084145938d9c236edb32f 100644 (file)
@@ -825,6 +825,22 @@ void ChineseCalendar::offsetMonth(int32_t newMoon, int32_t dom, int32_t delta) {
     }
 }
 
+constexpr uint32_t kChineseRelatedYearDiff = -2637;
+
+int32_t ChineseCalendar::getRelatedYear(UErrorCode &status) const
+{
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    if (U_FAILURE(status)) {
+        return 0;
+    }
+    return year + kChineseRelatedYearDiff;
+}
+
+void ChineseCalendar::setRelatedYear(int32_t year)
+{
+    // set extended year
+    set(UCAL_EXTENDED_YEAR, year - kChineseRelatedYearDiff);
+}
 
 // default century
 
index 016e9422e4392f49bf11fb5e9b5e67f93b71cc63..8e45fb20426e28fd2c86b46b5bd0d56975ab264d 100644 (file)
@@ -175,6 +175,20 @@ class U_I18N_API ChineseCalendar : public Calendar {
   virtual void roll(UCalendarDateFields field, int32_t amount, UErrorCode &status) override;
   virtual void roll(EDateFields field, int32_t amount, UErrorCode &status) override;
 
+  /**
+   * @return      The related Gregorian year; will be obtained by modifying the value
+   *              obtained by get from UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual int32_t getRelatedYear(UErrorCode &status) const override;
+
+  /**
+   * @param year  The related Gregorian year to set; will be modified as necessary then
+   *              set in UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual void setRelatedYear(int32_t year) override;
+
   //----------------------------------------------------------------------
   // Internal methods & astronomical calculations
   //----------------------------------------------------------------------
index 0be700ca0138d7a474bc22e3a8bdcffbe0ab0eb1..59609f63c2103f3483560dd0ac6c96de88f85b29 100644 (file)
@@ -96,6 +96,23 @@ CopticCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*status*/)
     internalSet(UCAL_DAY_OF_YEAR, (30 * month) + day);
 }
 
+constexpr uint32_t kCopticRelatedYearDiff = 284;
+
+int32_t CopticCalendar::getRelatedYear(UErrorCode &status) const
+{
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    if (U_FAILURE(status)) {
+        return 0;
+    }
+    return year + kCopticRelatedYearDiff;
+}
+
+void CopticCalendar::setRelatedYear(int32_t year)
+{
+    // set extended 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 
index 5c51af04ca0527636610c9aaafb5be4f86f76428..46f1d63c0a12229d36751ae6bef99d2436d1959c 100644 (file)
@@ -154,6 +154,20 @@ public:
      */
     const char * getType() const override;
 
+    /**
+     * @return      The related Gregorian year; will be obtained by modifying the value
+     *              obtained by get from UCAL_EXTENDED_YEAR field
+     * @internal
+     */
+    virtual int32_t getRelatedYear(UErrorCode &status) const override;
+
+    /**
+     * @param year  The related Gregorian year to set; will be modified as necessary then
+     *              set in UCAL_EXTENDED_YEAR field
+     * @internal
+     */
+    virtual void setRelatedYear(int32_t year) override;
+
 protected:
     //-------------------------------------------------------------------------
     // Calendar framework
index 59cdc661dac817f3d40ac755342668991cfd6a17..dad7bb97e2c8b0ed932cf9679058c48632e2270d 100644 (file)
@@ -141,6 +141,23 @@ const TimeZone* DangiCalendar::getDangiCalZoneAstroCalc(UErrorCode &status) cons
     return gDangiCalendarZoneAstroCalc;
 }
 
+constexpr uint32_t kDangiRelatedYearDiff = -2333;
+
+int32_t DangiCalendar::getRelatedYear(UErrorCode &status) const
+{
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    if (U_FAILURE(status)) {
+        return 0;
+    }
+    return year + kDangiRelatedYearDiff;
+}
+
+void DangiCalendar::setRelatedYear(int32_t year)
+{
+    // set extended year
+    set(UCAL_EXTENDED_YEAR, year - kDangiRelatedYearDiff);
+}
+
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DangiCalendar)
 
index 9d0437264ef175bdaa6edcf1193344b7065e92db..3cf4aaff20319bb95c9012f066473c90f8469853 100644 (file)
@@ -72,6 +72,20 @@ class DangiCalendar : public ChineseCalendar {
   // Internal methods & astronomical calculations
   //----------------------------------------------------------------------
 
+  /**
+   * @return      The related Gregorian year; will be obtained by modifying the value
+   *              obtained by get from UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual int32_t getRelatedYear(UErrorCode &status) const override;
+
+  /**
+   * @param year  The related Gregorian year to set; will be modified as necessary then
+   *              set in UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual void setRelatedYear(int32_t year) override;
+
  private:
 
   const TimeZone* getDangiCalZoneAstroCalc(UErrorCode &status) const;
index 07937872242c1adc7c8bb43138cba00913b56f4d..9b97b1ca33caa87316b15b8c4955b3db7f8bbd99 100644 (file)
@@ -136,6 +136,26 @@ EthiopicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType
     return CECalendar::handleGetLimit(field, limitType);
 }
 
+
+constexpr uint32_t kEthiopicRelatedYearDiff = 8;
+constexpr uint32_t kEthiopicAmeteAlemRelatedYearDiff = -5492;
+
+int32_t EthiopicCalendar::getRelatedYear(UErrorCode &status) const
+{
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    if (U_FAILURE(status)) {
+        return 0;
+    }
+    return year + (isAmeteAlemEra() ? kEthiopicAmeteAlemRelatedYearDiff : kEthiopicRelatedYearDiff);
+}
+
+void EthiopicCalendar::setRelatedYear(int32_t year)
+{
+    // set extended year
+    set(UCAL_EXTENDED_YEAR, year -
+        (isAmeteAlemEra() ? kEthiopicAmeteAlemRelatedYearDiff : 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 
index 0cc5b6c535ec3c0438fde0a758ab50fd8d438235..736ae1c565ad21cd0cef11eff1466986d9746d6a 100644 (file)
@@ -164,6 +164,20 @@ public:
      */
     UBool isAmeteAlemEra() const;
 
+    /**
+     * @return      The related Gregorian year; will be obtained by modifying the value
+     *              obtained by get from UCAL_EXTENDED_YEAR field
+     * @internal
+     */
+    virtual int32_t getRelatedYear(UErrorCode &status) const override;
+
+    /**
+     * @param year  The related Gregorian year to set; will be modified as necessary then
+     *              set in UCAL_EXTENDED_YEAR field
+     * @internal
+     */
+    virtual void setRelatedYear(int32_t year) override;
+
 protected:
     //-------------------------------------------------------------------------
     // Calendar framework
index 07aea83f64391926df6a253f03153bc221ba5ffe..6c47915fbe441eb3e01795703349088bcf3be06b 100644 (file)
@@ -666,6 +666,23 @@ int32_t HebrewCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UB
     return (int) (day + 347997);
 }
 
+constexpr uint32_t kHebrewRelatedYearDiff = -3760;
+
+int32_t HebrewCalendar::getRelatedYear(UErrorCode &status) const
+{
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    if (U_FAILURE(status)) {
+        return 0;
+    }
+    return year + kHebrewRelatedYearDiff;
+}
+
+void HebrewCalendar::setRelatedYear(int32_t year)
+{
+    // set extended 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 
index 34ce8c24c6843c17d5a206f74f3d01dc76584586..40a8f7a8f702643fdda437c889cea38f01940621 100644 (file)
@@ -273,6 +273,20 @@ public:
      */
     static UBool isLeapYear(int32_t year) ;
 
+    /**
+     * @return      The related Gregorian year; will be obtained by modifying the value
+     *              obtained by get from UCAL_EXTENDED_YEAR field
+     * @internal
+     */
+    virtual int32_t getRelatedYear(UErrorCode &status) const override;
+
+    /**
+     * @param year  The related Gregorian year to set; will be modified as necessary then
+     *              set in UCAL_EXTENDED_YEAR field
+     * @internal
+     */
+    virtual void setRelatedYear(int32_t year) override;
+
  protected:
 
     /**
index 80d38ca9d42d78e721f4b8a249d17982d3818efa..938b74ee0d23c5735b89bf85db728edc21e2e91e 100644 (file)
@@ -297,6 +297,23 @@ void IndianCalendar::handleComputeFields(int32_t julianDay, UErrorCode&  /* stat
    internalSet(UCAL_DAY_OF_YEAR, yday + 1); // yday is 0-based
 }    
 
+constexpr uint32_t kIndianRelatedYearDiff = 79;
+
+int32_t IndianCalendar::getRelatedYear(UErrorCode &status) const
+{
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    if (U_FAILURE(status)) {
+        return 0;
+    }
+    return year + kIndianRelatedYearDiff;
+}
+
+void IndianCalendar::setRelatedYear(int32_t year)
+{
+    // set extended 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
index e1c2f99295e8cd269975619976910a8feef06e1f..05d427316ca53959984f9aaf6dc12f5fd21bc04f 100644 (file)
@@ -284,6 +284,21 @@ public:
    */
   virtual const char * getType() const override;
 
+  /**
+   * @return      The related Gregorian year; will be obtained by modifying the value
+   *              obtained by get from UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual int32_t getRelatedYear(UErrorCode &status) const override;
+
+  /**
+   * @param year  The related Gregorian year to set; will be modified as necessary then
+   *              set in UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual void setRelatedYear(int32_t year) override;
+
+
 private:
   IndianCalendar() = delete; // default constructor not implemented
 
index 5b920f46a70ec3b10bdc8af6a1cdcc0881127f9b..54b2a97ff49447f33042d2549a487c55f52c808b 100644 (file)
@@ -692,6 +692,54 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status)
     internalSet(UCAL_DAY_OF_YEAR, dayOfYear);       
 }    
 
+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
+{
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    if (U_FAILURE(status)) {
+        return 0;
+    }
+    return gregoYearFromIslamicStart(year);
+}
+
+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;
+}
+
+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 
index 9e84353e4b04c79de6eba38f0f907181416de8b6..5ff212485e0aa36a6c57015e3f4a9ca0d4b9d13c 100644 (file)
@@ -376,6 +376,20 @@ class U_I18N_API IslamicCalendar : public Calendar {
    */
   virtual const char * getType() const override;
 
+  /**
+   * @return      The related Gregorian year; will be obtained by modifying the value
+   *              obtained by get from UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual int32_t getRelatedYear(UErrorCode &status) const override;
+
+  /**
+   * @param year  The related Gregorian year to set; will be modified as necessary then
+   *              set in UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual void setRelatedYear(int32_t year) override;
+
  private:
   IslamicCalendar() = delete; // default constructor not implemented
 
index bdbe296d232ac03eacfc35dfcfbdd300924d1809..a3f5e6ad4f5cfbc9fb06841d5ac246d04587abba 100644 (file)
@@ -233,6 +233,23 @@ void PersianCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*statu
     internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
 }    
 
+constexpr uint32_t kPersianRelatedYearDiff = 622;
+
+int32_t PersianCalendar::getRelatedYear(UErrorCode &status) const
+{
+    int32_t year = get(UCAL_EXTENDED_YEAR, status);
+    if (U_FAILURE(status)) {
+        return 0;
+    }
+    return year + kPersianRelatedYearDiff;
+}
+
+void PersianCalendar::setRelatedYear(int32_t year)
+{
+    // set extended year
+    set(UCAL_EXTENDED_YEAR, year - kPersianRelatedYearDiff);
+}
+
 // default century
 
 static UDate           gSystemDefaultCenturyStart       = DBL_MIN;
index 5111e01e5a1119161d992581726623347b1661a3..0d4c12535c214341f6f158b33800c14b9f47badc 100644 (file)
@@ -278,6 +278,20 @@ class PersianCalendar : public Calendar {
    */
   virtual const char * getType() const override;
 
+  /**
+   * @return      The related Gregorian year; will be obtained by modifying the value
+   *              obtained by get from UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual int32_t getRelatedYear(UErrorCode &status) const override;
+
+  /**
+   * @param year  The related Gregorian year to set; will be modified as necessary then
+   *              set in UCAL_EXTENDED_YEAR field
+   * @internal
+   */
+  virtual void setRelatedYear(int32_t year) override;
+
  private:
   PersianCalendar(); // default constructor not implemented