ICU-22679 Remove getType and string comparsion

Change the logic of handling year in era 0 counting backwards
to depend on a boolean virtual function instead of adding
string comparsion code in the base class to have specific knowledge of
behavior of subclass.
This commit is contained in:
Frank Tang 2024-03-18 00:02:16 -07:00 committed by Frank Yung-Fong Tang
parent 6b67715a94
commit 7a3dfe877d
12 changed files with 92 additions and 33 deletions

View file

@ -177,6 +177,8 @@ private:
* @internal
*/
virtual int32_t defaultCenturyStartYear() const override;
virtual bool isEra0CountingBackward() const override { return false; }
};
U_NAMESPACE_END

View file

@ -1826,16 +1826,11 @@ void Calendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& statu
// * If era==0 and years go backwards in time, change sign of amount.
// * Until we have new API per #9393, we temporarily hardcode knowledge of
// which calendars have era 0 years that go backwards.
UBool era0WithYearsThatGoBackwards = false;
int32_t era = get(UCAL_ERA, status);
if (era == 0) {
const char * calType = getType();
if ( uprv_strcmp(calType,"gregorian")==0 || uprv_strcmp(calType,"roc")==0 || uprv_strcmp(calType,"coptic")==0 ) {
if (uprv_mul32_overflow(amount, -1, &amount)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
era0WithYearsThatGoBackwards = true;
int32_t era = internalGet(UCAL_ERA);
if (era == 0 && isEra0CountingBackward()) {
if (uprv_mul32_overflow(amount, -1, &amount)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
}
int32_t newYear;
@ -1860,7 +1855,7 @@ void Calendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& statu
// else we are in era 0 with newYear < 1;
// calendars with years that go backwards must pin the year value at 0,
// other calendars can have years < 0 in era 0
} else if (era0WithYearsThatGoBackwards) {
} else if (era == 0 && isEra0CountingBackward()) {
newYear = 1;
}
set(field, newYear);
@ -2175,14 +2170,10 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status
// this by applying the amount to the UCAL_EXTENDED_YEAR field; but since
// we would still need to handle UCAL_YEAR_WOY as below, might as well
// also handle UCAL_YEAR the same way.
int32_t era = get(UCAL_ERA, status);
if (era == 0) {
const char * calType = getType();
if ( uprv_strcmp(calType,"gregorian")==0 || uprv_strcmp(calType,"roc")==0 || uprv_strcmp(calType,"coptic")==0 ) {
if (uprv_mul32_overflow(amount, -1, &amount)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
if (get(UCAL_ERA, status) == 0 && isEra0CountingBackward()) {
if (uprv_mul32_overflow(amount, -1, &amount)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
}
}

View file

@ -204,7 +204,7 @@ protected:
*/
virtual int32_t getJDEpochOffset() const override;
virtual bool isEra0CountingBackward() const override { return true; }
public:
/**
* Override Calendar Returns a unique class ID POLYMORPHICALLY. Pure virtual

View file

@ -90,6 +90,8 @@ class ISO8601Calendar : public GregorianCalendar {
*/
virtual const char * getType() const override;
protected:
virtual bool isEra0CountingBackward() const override { return false; }
private:

View file

@ -223,6 +223,8 @@ protected:
* @internal
*/
virtual int32_t getDefaultDayInMonth(int32_t eyear, int32_t month) override;
virtual bool isEra0CountingBackward() const override { return false; }
};
U_NAMESPACE_END

View file

@ -1547,6 +1547,13 @@ protected:
* @internal
*/
inline int32_t internalGet(UCalendarDateFields field) const {return fFields[field];}
/**
* The year in this calendar is counting from 1 backward if the era is 0.
* @return The year in era 0 of this calendar is counting backward from 1.
* @internal
*/
virtual bool isEra0CountingBackward() const { return false; }
#endif /* U_HIDE_INTERNAL_API */
/**

View file

@ -619,6 +619,15 @@ public:
*/
virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override;
#ifndef U_HIDE_INTERNAL_API
/**
* The year in this calendar is counting from 1 backward if the era is 0.
* @return The year in era 0 of this calendar is counting backward from 1.
* @internal
*/
virtual bool isEra0CountingBackward() const override { return true; }
#endif // U_HIDE_INTERNAL_API
private:
/**
* Compute the julian day number of the given year.

View file

@ -244,4 +244,15 @@ public class BuddhistCalendar extends GregorianCalendar {
public String getType() {
return "buddhist";
}
/*
* {@inheritDoc}
* @internal
* @deprecated This API is ICU internal only.
*/
@Override
@Deprecated
protected boolean isEra0CountingBackward() {
return false;
}
}

View file

@ -3072,14 +3072,9 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
// * Until we have new API per #9393, we temporarily hardcode knowledge of
// which calendars have era 0 years that go backwards.
{
boolean era0WithYearsThatGoBackwards = false;
int era = get(ERA);
if (era == 0) {
String calType = getType();
if (calType.equals("gregorian") || calType.equals("roc") || calType.equals("coptic")) {
amount = -amount;
era0WithYearsThatGoBackwards = true;
}
if (era == 0 && isEra0CountingBackward()) {
amount = -amount;
}
int newYear = internalGet(field) + amount;
if (era > 0 || newYear >= 1) {
@ -3098,7 +3093,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
// else we are in era 0 with newYear < 1;
// calendars with years that go backwards must pin the year value at 0,
// other calendars can have years < 0 in era 0
} else if (era0WithYearsThatGoBackwards) {
} else if (era == 0 && isEra0CountingBackward()) {
newYear = 1;
}
set(field, newYear);
@ -3415,11 +3410,8 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
// also handle YEAR the same way.
{
int era = get(ERA);
if (era == 0) {
String calType = getType();
if (calType.equals("gregorian") || calType.equals("roc") || calType.equals("coptic")) {
amount = -amount;
}
if (era == 0 && isEra0CountingBackward()) {
amount = -amount;
}
}
// Fall through into standard handling
@ -4098,6 +4090,17 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
}
}
/*
* The year in this calendar is counting from 1 backward if the era is 0.
* @return The year in era 0 of this calendar is counting backward from 1.
* @internal
* @deprecated This API is ICU internal only.
*/
@Deprecated
protected boolean isEra0CountingBackward() {
return false;
}
/**
* Returns the week number of a day, within a period. This may be the week number in
* a year or the week number in a month. Usually this will be a value &gt;= 1, but if

View file

@ -242,6 +242,17 @@ public final class CopticCalendar extends CECalendar
return "coptic";
}
/*
* {@inheritDoc}
* @internal
* @deprecated This API is ICU internal only.
*/
@Override
@Deprecated
protected boolean isEra0CountingBackward() {
return true;
}
/**
* {@inheritDoc}
* @internal

View file

@ -896,6 +896,17 @@ public class GregorianCalendar extends Calendar {
return "gregorian";
}
/*
* {@inheritDoc}
* @internal
* @deprecated This API is ICU internal only.
*/
@Override
@Deprecated
protected boolean isEra0CountingBackward() {
return true;
}
/*
private static CalendarFactory factory;
public static CalendarFactory factory() {

View file

@ -484,4 +484,14 @@ public class JapaneseCalendar extends GregorianCalendar {
return super.getActualMaximum(field);
}
/*
* {@inheritDoc}
* @internal
* @deprecated This API is ICU internal only.
*/
@Override
@Deprecated
protected boolean isEra0CountingBackward() {
return false;
}
}