Skip to content

Commit

Permalink
ICU-22633 Return error if era is out of range
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankYFTang committed Feb 27, 2024
1 parent 314f03e commit ec800e7
Show file tree
Hide file tree
Showing 26 changed files with 113 additions and 34 deletions.
5 changes: 4 additions & 1 deletion icu4c/source/i18n/buddhcal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ const char *BuddhistCalendar::getType() const
return "buddhist";
}

int32_t BuddhistCalendar::handleGetExtendedYear()
int32_t BuddhistCalendar::handleGetExtendedYear(UErrorCode& status)
{
if (U_FAILURE(status)) {
return 0;
}
// EXTENDED_YEAR in BuddhistCalendar is a Gregorian year.
// The default value of EXTENDED_YEAR is 1970 (Buddhist 2513)
int32_t year;
Expand Down
3 changes: 2 additions & 1 deletion icu4c/source/i18n/buddhcal.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,11 @@ class BuddhistCalendar : public GregorianCalendar {
* use the UCAL_EXTENDED_YEAR field or the UCAL_YEAR and supra-year fields (such
* as UCAL_ERA) specific to the calendar system, depending on which set of
* fields is newer.
* @param status
* @return the extended year
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
/**
* Subclasses may override this method to compute several fields
* specific to each calendar system.
Expand Down
15 changes: 12 additions & 3 deletions icu4c/source/i18n/calendar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2929,11 +2929,17 @@ void Calendar::validateField(UCalendarDateFields field, UErrorCode &status) {
int32_t y;
switch (field) {
case UCAL_DAY_OF_MONTH:
y = handleGetExtendedYear();
y = handleGetExtendedYear(status);
if (U_FAILURE(status)) {
return;
}
validateField(field, 1, handleGetMonthLength(y, internalGetMonth()), status);
break;
case UCAL_DAY_OF_YEAR:
y = handleGetExtendedYear();
y = handleGetExtendedYear(status);
if (U_FAILURE(status)) {
return;
}
validateField(field, 1, handleGetYearLength(y), status);
break;
case UCAL_DAY_OF_WEEK_IN_MONTH:
Expand Down Expand Up @@ -3387,7 +3393,10 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
if (bestField == UCAL_WEEK_OF_YEAR && newerField(UCAL_YEAR_WOY, UCAL_YEAR) == UCAL_YEAR_WOY) {
year = internalGet(UCAL_YEAR_WOY);
} else {
year = handleGetExtendedYear();
year = handleGetExtendedYear(status);
if (U_FAILURE(status)) {
return 0;
}
}

internalSet(UCAL_EXTENDED_YEAR, year);
Expand Down
6 changes: 5 additions & 1 deletion icu4c/source/i18n/chnsecal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,11 @@ int32_t ChineseCalendar::handleGetLimit(UCalendarDateFields field, ELimitType li
* field as the continuous year count, depending on which is newer.
* @stable ICU 2.8
*/
int32_t ChineseCalendar::handleGetExtendedYear() {
int32_t ChineseCalendar::handleGetExtendedYear(UErrorCode& status) {
if (U_FAILURE(status)) {
return 0;
}

int32_t year;
if (newestStamp(UCAL_ERA, UCAL_YEAR, kUnset) <= fStamp[UCAL_EXTENDED_YEAR]) {
year = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1
Expand Down
2 changes: 1 addition & 1 deletion icu4c/source/i18n/chnsecal.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class U_I18N_API ChineseCalendar : public Calendar {
virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const override;
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override;
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const override;
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override;
virtual const UFieldResolutionTable* getFieldResolutionTable() const override;

Expand Down
10 changes: 8 additions & 2 deletions icu4c/source/i18n/coptccal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ CopticCalendar::getType() const
//-------------------------------------------------------------------------

int32_t
CopticCalendar::handleGetExtendedYear()
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
Expand All @@ -67,8 +70,11 @@ CopticCalendar::handleGetExtendedYear()
int32_t era = internalGet(UCAL_ERA, CE);
if (era == BCE) {
eyear = 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year
} else {
} else if (era == CE){
eyear = internalGet(UCAL_YEAR, 1); // Default to year 1
} else {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
}
return eyear;
Expand Down
2 changes: 1 addition & 1 deletion icu4c/source/i18n/coptccal.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class CopticCalendar : public CECalendar {
* Return the extended year defined by the current fields.
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;

/**
* Compute fields from the JD
Expand Down
10 changes: 8 additions & 2 deletions icu4c/source/i18n/ethpccal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ EthiopicCalendar::getType() const
//-------------------------------------------------------------------------

int32_t
EthiopicCalendar::handleGetExtendedYear()
EthiopicCalendar::handleGetExtendedYear(UErrorCode& status)
{
if (U_FAILURE(status)) {
return 0;
}
// Ethiopic calendar uses EXTENDED_YEAR aligned to
// Amelete Hihret year always.
if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
Expand Down Expand Up @@ -181,8 +184,11 @@ EthiopicAmeteAlemCalendar::getType() const
}

int32_t
EthiopicAmeteAlemCalendar::handleGetExtendedYear()
EthiopicAmeteAlemCalendar::handleGetExtendedYear(UErrorCode& status)
{
if (U_FAILURE(status)) {
return 0;
}
// Ethiopic calendar uses EXTENDED_YEAR aligned to
// Amelete Hihret year always.
if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
Expand Down
4 changes: 2 additions & 2 deletions icu4c/source/i18n/ethpccal.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class EthiopicCalendar : public CECalendar {
* 1 AMETE_MIHRET 1
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;

/**
* Compute fields from the JD
Expand Down Expand Up @@ -341,7 +341,7 @@ class EthiopicAmeteAlemCalendar : public EthiopicCalendar {
* 1 AMETE_ALEM 5501
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;

/**
* Compute fields from the JD
Expand Down
10 changes: 8 additions & 2 deletions icu4c/source/i18n/gregocal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,10 @@ int32_t GregorianCalendar::getActualMaximum(UCalendarDateFields field, UErrorCod
}


int32_t GregorianCalendar::handleGetExtendedYear() {
int32_t GregorianCalendar::handleGetExtendedYear(UErrorCode& status) {
if (U_FAILURE(status)) {
return 0;
}
// the year to return
int32_t year = kEpochYear;

Expand All @@ -1184,8 +1187,11 @@ int32_t GregorianCalendar::handleGetExtendedYear() {
int32_t era = internalGet(UCAL_ERA, AD);
if (era == BC) {
year = 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year
} else {
} else if (era == AD) {
year = internalGet(UCAL_YEAR, kEpochYear);
} else {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
}
break;
Expand Down
14 changes: 11 additions & 3 deletions icu4c/source/i18n/hebrwcal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,10 @@ int32_t HebrewCalendar::handleGetYearLength(int32_t eyear) const {

void HebrewCalendar::validateField(UCalendarDateFields field, UErrorCode &status) {
if ((field == UCAL_MONTH || field == UCAL_ORDINAL_MONTH)
&& !isLeapYear(handleGetExtendedYear()) && internalGetMonth() == ADAR_1) {
&& !isLeapYear(handleGetExtendedYear(status)) && internalGetMonth() == ADAR_1) {
if (U_FAILURE(status)) {
return;
}
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
Expand Down Expand Up @@ -636,7 +639,10 @@ void HebrewCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status)
/**
* @internal
*/
int32_t HebrewCalendar::handleGetExtendedYear() {
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
Expand Down Expand Up @@ -783,7 +789,9 @@ int32_t HebrewCalendar::internalGetMonth() const {
int32_t ordinalMonth = internalGet(UCAL_ORDINAL_MONTH);
HebrewCalendar *nonConstThis = (HebrewCalendar*)this; // cast away const

int32_t year = nonConstThis->handleGetExtendedYear();
UErrorCode status = U_ZERO_ERROR;
int32_t year = nonConstThis->handleGetExtendedYear(status);
U_ASSERT(U_SUCCESS(status));
return ordinalMonth + (((!isLeapYear(year)) && (ordinalMonth > ADAR_1)) ? 1: 0);
}
return Calendar::internalGetMonth();
Expand Down
3 changes: 2 additions & 1 deletion icu4c/source/i18n/hebrwcal.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,11 @@ class U_I18N_API HebrewCalendar : public Calendar {
* use the UCAL_EXTENDED_YEAR field or the UCAL_YEAR and supra-year fields (such
* as UCAL_ERA) specific to the calendar system, depending on which set of
* fields is newer.
* @param status
* @return the extended year
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
/**
* Return the Julian day number of day before the first day of the
* given month in the given extended year. Subclasses should override
Expand Down
5 changes: 4 additions & 1 deletion icu4c/source/i18n/indiancal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,10 @@ int64_t IndianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UB
// Functions for converting from milliseconds to field values
//-------------------------------------------------------------------------

int32_t IndianCalendar::handleGetExtendedYear() {
int32_t IndianCalendar::handleGetExtendedYear(UErrorCode& status) {
if (U_FAILURE(status)) {
return 0;
}
int32_t year;

if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
Expand Down
2 changes: 1 addition & 1 deletion icu4c/source/i18n/indiancal.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class U_I18N_API IndianCalendar : public Calendar {
/**
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;

/**
* Override Calendar to compute several fields specific to the Indian
Expand Down
5 changes: 4 additions & 1 deletion icu4c/source/i18n/islamcal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,10 @@ int64_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, U
/**
* @draft ICU 2.4
*/
int32_t IslamicCalendar::handleGetExtendedYear() {
int32_t IslamicCalendar::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
Expand Down
2 changes: 1 addition & 1 deletion icu4c/source/i18n/islamcal.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ class U_I18N_API IslamicCalendar : public Calendar {
/**
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;

/**
* Override Calendar to compute several fields specific to the Islamic
Expand Down
10 changes: 7 additions & 3 deletions icu4c/source/i18n/japancal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,11 @@ int32_t JapaneseCalendar::internalGetEra() const
return internalGet(UCAL_ERA, gCurrentEra);
}

int32_t JapaneseCalendar::handleGetExtendedYear()
int32_t JapaneseCalendar::handleGetExtendedYear(UErrorCode& status)
{
if (U_FAILURE(status)) {
return 0;
}
// EXTENDED_YEAR in JapaneseCalendar is a Gregorian year
// The default value of EXTENDED_YEAR is 1970 (Showa 45)
int32_t year;
Expand All @@ -201,9 +204,10 @@ int32_t JapaneseCalendar::handleGetExtendedYear()
newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) {
year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch);
} else {
UErrorCode status = U_ZERO_ERROR;
int32_t eraStartYear = gJapaneseEraRules->getStartYear(internalGet(UCAL_ERA, gCurrentEra), status);
U_ASSERT(U_SUCCESS(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)
Expand Down
2 changes: 1 addition & 1 deletion icu4c/source/i18n/japancal.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class JapaneseCalendar : public GregorianCalendar {
* Japanese calendar case, this is equal to the equivalent extended Gregorian year.
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;

/**
* Return the maximum value that this field could have, given the current date.
Expand Down
5 changes: 4 additions & 1 deletion icu4c/source/i18n/persncal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,10 @@ int64_t PersianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, U
// Functions for converting from milliseconds to field values
//-------------------------------------------------------------------------

int32_t PersianCalendar::handleGetExtendedYear() {
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
Expand Down
2 changes: 1 addition & 1 deletion icu4c/source/i18n/persncal.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ class PersianCalendar : public Calendar {
/**
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;

/**
* Override Calendar to compute several fields specific to the Persian
Expand Down
9 changes: 8 additions & 1 deletion icu4c/source/i18n/taiwncal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,12 @@ const char *TaiwanCalendar::getType() const
return "roc";
}

int32_t TaiwanCalendar::handleGetExtendedYear()
int32_t TaiwanCalendar::handleGetExtendedYear(UErrorCode& status)
{
if (U_FAILURE(status)) {
return 0;
}

// EXTENDED_YEAR in TaiwanCalendar is a Gregorian year
// The default value of EXTENDED_YEAR is 1970 (Minguo 59)
int32_t year = kGregorianEpoch;
Expand All @@ -78,6 +82,9 @@ int32_t TaiwanCalendar::handleGetExtendedYear()
year = internalGet(UCAL_YEAR, 1) + kTaiwanEraStart;
} else if(era == BEFORE_MINGUO) {
year = 1 - internalGet(UCAL_YEAR, 1) + kTaiwanEraStart;
} else {
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
}
return year;
Expand Down
2 changes: 1 addition & 1 deletion icu4c/source/i18n/taiwncal.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class TaiwanCalendar : public GregorianCalendar {
* @return the extended year
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
/**
* Subclasses may override this method to compute several fields
* specific to each calendar system.
Expand Down
3 changes: 2 additions & 1 deletion icu4c/source/i18n/unicode/calendar.h
Original file line number Diff line number Diff line change
Expand Up @@ -1694,10 +1694,11 @@ class U_I18N_API Calendar : public UObject {
* use the UCAL_EXTENDED_YEAR field or the UCAL_YEAR and supra-year fields (such
* as UCAL_ERA) specific to the calendar system, depending on which set of
* fields is newer.
* @param status ICU Error Code
* @return the extended year
* @internal
*/
virtual int32_t handleGetExtendedYear() = 0;
virtual int32_t handleGetExtendedYear(UErrorCode& status) = 0;

/**
* Subclasses may override this. This method calls
Expand Down
3 changes: 2 additions & 1 deletion icu4c/source/i18n/unicode/gregocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -583,10 +583,11 @@ class U_I18N_API GregorianCalendar: public Calendar {
* use the UCAL_EXTENDED_YEAR field or the UCAL_YEAR and supra-year fields (such
* as UCAL_ERA) specific to the calendar system, depending on which set of
* fields is newer.
* @param status
* @return the extended year
* @internal
*/
virtual int32_t handleGetExtendedYear() override;
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;

/**
* Subclasses may override this to convert from week fields
Expand Down
Loading

0 comments on commit ec800e7

Please sign in to comment.