mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-07 14:31:31 +00:00
ICU-22633 Return error if era is out of range
This commit is contained in:
parent
314f03eeaf
commit
ec800e7407
26 changed files with 113 additions and 34 deletions
|
@ -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;
|
||||
|
|
|
@ -139,10 +139,11 @@ private:
|
|||
* 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.
|
||||
|
|
|
@ -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:
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -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;
|
||||
|
|
|
@ -177,7 +177,7 @@ protected:
|
|||
* 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
|
||||
|
|
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
|
|
@ -169,7 +169,7 @@ protected:
|
|||
* 1 AMETE_MIHRET 1
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetExtendedYear() override;
|
||||
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
|
||||
|
||||
/**
|
||||
* Compute fields from the JD
|
||||
|
@ -341,7 +341,7 @@ protected:
|
|||
* 1 AMETE_ALEM 5501
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetExtendedYear() override;
|
||||
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
|
||||
|
||||
/**
|
||||
* Compute fields from the JD
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
|
|
@ -350,10 +350,11 @@ public:
|
|||
* 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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -234,7 +234,7 @@ public:
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetExtendedYear() override;
|
||||
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
|
||||
|
||||
/**
|
||||
* Override Calendar to compute several fields specific to the Indian
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -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)
|
||||
|
|
|
@ -123,7 +123,7 @@ public:
|
|||
* 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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -139,7 +139,7 @@ private:
|
|||
* @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.
|
||||
|
|
|
@ -1694,10 +1694,11 @@ protected:
|
|||
* 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
|
||||
|
|
|
@ -583,10 +583,11 @@ public:
|
|||
* 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
|
||||
|
|
|
@ -106,6 +106,7 @@ void IntlCalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &n
|
|||
TESTCASE_AUTO(TestConsistencyPersian);
|
||||
TESTCASE_AUTO(TestConsistencyJapanese);
|
||||
TESTCASE_AUTO(TestIslamicUmalquraCalendarSlow);
|
||||
TESTCASE_AUTO(TestJapaneseLargeEra);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
|
@ -1135,6 +1136,17 @@ void IntlCalendarTest::TestIslamicUmalquraCalendarSlow() {
|
|||
status.reset();
|
||||
}
|
||||
|
||||
void IntlCalendarTest::TestJapaneseLargeEra() {
|
||||
IcuTestErrorCode status(*this, "TestJapaneseLargeEra");
|
||||
Locale l("ja@calendar=japanese");
|
||||
std::unique_ptr<Calendar> cal(
|
||||
Calendar::createInstance(l, status));
|
||||
cal->clear();
|
||||
cal->set(UCAL_ERA, 2139062143);
|
||||
cal->add(UCAL_YEAR, 1229539657, status);
|
||||
status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
|
||||
}
|
||||
|
||||
void IntlCalendarTest::simpleTest(const Locale& loc, const UnicodeString& expect, UDate expectDate, UErrorCode& status)
|
||||
{
|
||||
UnicodeString tmp;
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
void TestConsistencyPersian();
|
||||
void TestConsistencyJapanese();
|
||||
void TestIslamicUmalquraCalendarSlow();
|
||||
void TestJapaneseLargeEra();
|
||||
|
||||
protected:
|
||||
// Test a Gregorian-Like calendar
|
||||
|
|
Loading…
Add table
Reference in a new issue