mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-13 08:53:20 +00:00
ICU-10752 Spread (s|g)etRelativeYear to subclass
Remove the switch statment implementaiton in Calendar::(g|s)etRelatedYear and move the code into each subclass as proper OOP style.
This commit is contained in:
parent
b00562e989
commit
b0ab1171ad
17 changed files with 283 additions and 117 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue