mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 15:42:14 +00:00
ICU-22633 Test and fix int32_t overflow for Calendar set
Add test to set with INT32_MAX and INT32_MIN then call getTime() and fix all the undefined errors.
This commit is contained in:
parent
18c7d48b3e
commit
d43d216feb
26 changed files with 474 additions and 165 deletions
|
@ -74,9 +74,12 @@ int32_t BuddhistCalendar::handleGetExtendedYear(UErrorCode& status)
|
|||
if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
|
||||
year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch);
|
||||
} else {
|
||||
// extended year is a gregorian year, where 1 = 1AD, 0 = 1BC, -1 = 2BC, etc
|
||||
year = internalGet(UCAL_YEAR, kGregorianEpoch - kBuddhistEraStart)
|
||||
+ kBuddhistEraStart;
|
||||
// extended year is a gregorian year, where 1 = 1AD, 0 = 1BC, -1 = 2BC, etc
|
||||
year = internalGet(UCAL_YEAR, kGregorianEpoch - kBuddhistEraStart);
|
||||
if (uprv_add32_overflow(year, kBuddhistEraStart, &year)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return year;
|
||||
}
|
||||
|
|
|
@ -2929,7 +2929,7 @@ void Calendar::validateField(UCalendarDateFields field, UErrorCode &status) {
|
|||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
validateField(field, 1, handleGetMonthLength(y, internalGetMonth()), status);
|
||||
validateField(field, 1, handleGetMonthLength(y, internalGetMonth(status), status), status);
|
||||
break;
|
||||
case UCAL_DAY_OF_YEAR:
|
||||
y = handleGetExtendedYear(status);
|
||||
|
@ -3146,7 +3146,7 @@ void Calendar::computeTime(UErrorCode& status) {
|
|||
|
||||
UDate t = 0;
|
||||
if (fStamp[UCAL_ZONE_OFFSET] >= ((int32_t)kMinimumUserStamp) || fStamp[UCAL_DST_OFFSET] >= ((int32_t)kMinimumUserStamp)) {
|
||||
t = millis + millisInDay - (internalGet(UCAL_ZONE_OFFSET) + internalGet(UCAL_DST_OFFSET));
|
||||
t = millis + millisInDay - internalGet(UCAL_ZONE_OFFSET) - internalGet(UCAL_DST_OFFSET);
|
||||
} else {
|
||||
// Compute the time zone offset and DST offset. There are two potential
|
||||
// ambiguities here. We'll assume a 2:00 am (wall time) switchover time
|
||||
|
@ -3416,12 +3416,21 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
|
|||
int32_t month;
|
||||
|
||||
if(isSet(UCAL_MONTH) || isSet(UCAL_ORDINAL_MONTH)) {
|
||||
month = internalGetMonth();
|
||||
month = internalGetMonth(status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
month = getDefaultMonthInYear(year);
|
||||
month = getDefaultMonthInYear(year, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t julianDay = handleComputeMonthStart(year, useMonth ? month : 0, useMonth);
|
||||
int32_t julianDay = handleComputeMonthStart(year, useMonth ? month : 0, useMonth, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bestField == UCAL_DAY_OF_MONTH) {
|
||||
|
||||
|
@ -3467,7 +3476,10 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
|
|||
first += 7;
|
||||
}
|
||||
|
||||
int32_t dowLocal = getLocalDOW();
|
||||
int32_t dowLocal = getLocalDOW(status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find the first target DOW (dowLocal) in the month or year.
|
||||
// Actually, it may be just before the first of the month or year.
|
||||
|
@ -3484,7 +3496,12 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
|
|||
// negative.
|
||||
int32_t dim = internalGet(UCAL_DAY_OF_WEEK_IN_MONTH, 1);
|
||||
if (dim >= 0) {
|
||||
date += 7*(dim - 1);
|
||||
int32_t temp;
|
||||
if (uprv_mul32_overflow(7, dim - 1, &temp) ||
|
||||
uprv_add32_overflow(date, temp, &date)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Move date to the last of this day-of-week in this month,
|
||||
|
@ -3493,9 +3510,18 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
|
|||
// past the first of the given day-of-week in this month.
|
||||
// Note that we handle -2, -3, etc. correctly, even though
|
||||
// values < -1 are technically disallowed.
|
||||
int32_t m = internalGetMonth(UCAL_JANUARY);
|
||||
int32_t monthLength = handleGetMonthLength(year, m);
|
||||
date += ((monthLength - date) / 7 + dim + 1) * 7;
|
||||
int32_t m = internalGetMonth(UCAL_JANUARY, status);
|
||||
int32_t monthLength = handleGetMonthLength(year, m, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
int32_t temp;
|
||||
if (uprv_add32_overflow((monthLength - date) / 7, dim+1, &temp) ||
|
||||
uprv_mul32_overflow(temp, 7, &temp) ||
|
||||
uprv_add32_overflow(date, temp, &date)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if defined (U_DEBUG_CAL)
|
||||
|
@ -3510,7 +3536,10 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
|
|||
// need to be sure to stay in 'real' year.
|
||||
int32_t woy = internalGet(bestField);
|
||||
|
||||
int32_t nextJulianDay = handleComputeMonthStart(year+1, 0, false); // jd of day before jan 1
|
||||
int32_t nextJulianDay = handleComputeMonthStart(year+1, 0, false, status); // jd of day before jan 1
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
int32_t nextFirst = julianDayToDayOfWeek(nextJulianDay + 1) - firstDayOfWeek;
|
||||
|
||||
if (nextFirst < 0) { // 0..6 ldow of Jan 1
|
||||
|
@ -3553,7 +3582,12 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
|
|||
}
|
||||
|
||||
// Now adjust for the week number.
|
||||
testDate += 7 * (woy - 1);
|
||||
int32_t weeks;
|
||||
if (uprv_mul32_overflow(woy-1, 7, &weeks) ||
|
||||
uprv_add32_overflow(weeks, testDate, &testDate)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (U_DEBUG_CAL)
|
||||
fprintf(stderr, "%s:%d - y=%d, y-1=%d doy%d, njd%d (C.F. %d)\n",
|
||||
|
@ -3561,7 +3595,10 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
|
|||
#endif
|
||||
if(julianDay+testDate > nextJulianDay) { // is it past Dec 31? (nextJulianDay is day BEFORE year+1's Jan 1)
|
||||
// Fire up the calculating engines.. retry YWOY = (year-1)
|
||||
julianDay = handleComputeMonthStart(year-1, 0, false); // jd before Jan 1 of previous year
|
||||
julianDay = handleComputeMonthStart(year-1, 0, false, status); // jd before Jan 1 of previous year
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
first = julianDayToDayOfWeek(julianDay + 1) - firstDayOfWeek; // 0 based local dow of first week
|
||||
|
||||
if(first < 0) { // 0..6
|
||||
|
@ -3587,14 +3624,24 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField, UErrorCo
|
|||
}
|
||||
|
||||
// Now adjust for the week number.
|
||||
date += 7 * (internalGet(bestField) - 1);
|
||||
int32_t weeks = internalGet(bestField);
|
||||
if (uprv_add32_overflow(weeks, -1, &weeks) ||
|
||||
uprv_mul32_overflow(7, weeks, &weeks) ||
|
||||
uprv_add32_overflow(date, weeks, &date)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return julianDay + date;
|
||||
if (uprv_add32_overflow(julianDay, date, &julianDay)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
return julianDay;
|
||||
}
|
||||
|
||||
int32_t
|
||||
Calendar::getDefaultMonthInYear(int32_t /*eyear*/)
|
||||
Calendar::getDefaultMonthInYear(int32_t /*eyear*/, UErrorCode& /* status */)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -3606,17 +3653,28 @@ Calendar::getDefaultDayInMonth(int32_t /*eyear*/, int32_t /*month*/)
|
|||
}
|
||||
|
||||
|
||||
int32_t Calendar::getLocalDOW()
|
||||
int32_t Calendar::getLocalDOW(UErrorCode& status)
|
||||
{
|
||||
// Get zero-based localized DOW, valid range 0..6. This is the DOW
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
// Get zero-based localized DOW, valid range 0..6. This is the DOW
|
||||
// we are looking for.
|
||||
int32_t dowLocal = 0;
|
||||
switch (resolveFields(kDOWPrecedence)) {
|
||||
case UCAL_DAY_OF_WEEK:
|
||||
dowLocal = internalGet(UCAL_DAY_OF_WEEK) - fFirstDayOfWeek;
|
||||
dowLocal = internalGet(UCAL_DAY_OF_WEEK);
|
||||
if (uprv_add32_overflow(dowLocal, -fFirstDayOfWeek, &dowLocal)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case UCAL_DOW_LOCAL:
|
||||
dowLocal = internalGet(UCAL_DOW_LOCAL) - 1;
|
||||
dowLocal = internalGet(UCAL_DOW_LOCAL);
|
||||
if (uprv_add32_overflow(dowLocal, -1, &dowLocal)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -3628,8 +3686,11 @@ int32_t Calendar::getLocalDOW()
|
|||
return dowLocal;
|
||||
}
|
||||
|
||||
int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy)
|
||||
int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy, UErrorCode& status)
|
||||
{
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
// We have UCAL_YEAR_WOY and UCAL_WEEK_OF_YEAR - from those, determine
|
||||
// what year we fall in, so that other code can set it properly.
|
||||
// (code borrowed from computeWeekFields and handleComputeJulianDay)
|
||||
|
@ -3639,10 +3700,21 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
|
|||
UCalendarDateFields bestField = resolveFields(kDatePrecedence); // !! Note: if subclasses have a different table, they should override handleGetExtendedYearFromWeekFields
|
||||
|
||||
// Now, a local DOW
|
||||
int32_t dowLocal = getLocalDOW(); // 0..6
|
||||
int32_t dowLocal = getLocalDOW(status); // 0..6
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
int32_t firstDayOfWeek = getFirstDayOfWeek(); // Localized fdw
|
||||
int32_t jan1Start = handleComputeMonthStart(yearWoy, 0, false);
|
||||
int32_t nextJan1Start = handleComputeMonthStart(yearWoy+1, 0, false); // next year's Jan1 start
|
||||
int32_t jan1Start = handleComputeMonthStart(yearWoy, 0, false, status);
|
||||
int32_t yearWoyPlus1;
|
||||
if (uprv_add32_overflow(yearWoy, 1, &yearWoyPlus1)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
int32_t nextJan1Start = handleComputeMonthStart(yearWoyPlus1, 0, false, status); // next year's Jan1 start
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// At this point julianDay is the 0-based day BEFORE the first day of
|
||||
// January 1, year 1 of the given calendar. If julianDay == 0, it
|
||||
|
@ -3719,7 +3791,10 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
|
|||
|
||||
case UCAL_DATE:
|
||||
{
|
||||
int32_t m = internalGetMonth();
|
||||
int32_t m = internalGetMonth(status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
if((m == 0) &&
|
||||
(woy >= getLeastMaximum(UCAL_WEEK_OF_YEAR))) {
|
||||
return yearWoy+1; // month 0, late woy = in the next year
|
||||
|
@ -3743,16 +3818,19 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
|
|||
}
|
||||
}
|
||||
|
||||
int32_t Calendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const
|
||||
int32_t Calendar::handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const
|
||||
{
|
||||
return handleComputeMonthStart(extendedYear, month+1, true) -
|
||||
handleComputeMonthStart(extendedYear, month, true);
|
||||
return handleComputeMonthStart(extendedYear, month+1, true, status) -
|
||||
handleComputeMonthStart(extendedYear, month, true, status);
|
||||
}
|
||||
|
||||
int32_t Calendar::handleGetYearLength(int32_t eyear) const
|
||||
{
|
||||
return handleComputeMonthStart(eyear+1, 0, false) -
|
||||
handleComputeMonthStart(eyear, 0, false);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t result = handleComputeMonthStart(eyear+1, 0, false, status) -
|
||||
handleComputeMonthStart(eyear, 0, false, status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
@ -3776,7 +3854,7 @@ Calendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const
|
|||
}
|
||||
cal->setLenient(true);
|
||||
cal->prepareGetActual(field,false,status);
|
||||
result = handleGetMonthLength(cal->get(UCAL_EXTENDED_YEAR, status), cal->get(UCAL_MONTH, status));
|
||||
result = handleGetMonthLength(cal->get(UCAL_EXTENDED_YEAR, status), cal->get(UCAL_MONTH, status), status);
|
||||
delete cal;
|
||||
}
|
||||
break;
|
||||
|
@ -4181,14 +4259,17 @@ Calendar::internalSet(EDateFields field, int32_t value)
|
|||
internalSet((UCalendarDateFields) field, value);
|
||||
}
|
||||
|
||||
int32_t Calendar::internalGetMonth() const {
|
||||
if (resolveFields(kMonthPrecedence) == UCAL_MONTH) {
|
||||
return internalGet(UCAL_MONTH);
|
||||
int32_t Calendar::internalGetMonth(UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
return internalGet(UCAL_ORDINAL_MONTH);
|
||||
if (resolveFields(kMonthPrecedence) == UCAL_MONTH) {
|
||||
return internalGet(UCAL_MONTH, status);
|
||||
}
|
||||
return internalGet(UCAL_ORDINAL_MONTH, status);
|
||||
}
|
||||
|
||||
int32_t Calendar::internalGetMonth(int32_t defaultValue) const {
|
||||
int32_t Calendar::internalGetMonth(int32_t defaultValue, UErrorCode& /* status */) const {
|
||||
if (resolveFields(kMonthPrecedence) == UCAL_MONTH) {
|
||||
return internalGet(UCAL_MONTH, defaultValue);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ CECalendar::operator=(const CECalendar& right)
|
|||
//-------------------------------------------------------------------------
|
||||
|
||||
int64_t
|
||||
CECalendar::handleComputeMonthStart(int32_t eyear,int32_t emonth, UBool /*useMonth*/) const
|
||||
CECalendar::handleComputeMonthStart(int32_t eyear,int32_t emonth, UBool /*useMonth*/, UErrorCode& /*status*/) const
|
||||
{
|
||||
int64_t year64 = eyear;
|
||||
// handle month > 12, < 0 (e.g. from add/set)
|
||||
|
|
|
@ -98,7 +98,7 @@ protected:
|
|||
* Return JD of start of given month/extended year
|
||||
* @internal
|
||||
*/
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const override;
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Calculate the limit for a specified type of limit and field
|
||||
|
|
|
@ -256,8 +256,12 @@ int32_t ChineseCalendar::handleGetExtendedYear(UErrorCode& status) {
|
|||
* whether or not the given month is a leap month.
|
||||
* @stable ICU 2.8
|
||||
*/
|
||||
int32_t ChineseCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
|
||||
int32_t thisStart = handleComputeMonthStart(extendedYear, month, true) -
|
||||
int32_t ChineseCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const {
|
||||
int32_t thisStart = handleComputeMonthStart(extendedYear, month, true, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
thisStart = thisStart -
|
||||
kEpochStartAsJulianDay + 1; // Julian day -> local days
|
||||
int32_t nextStart = newMoonNear(thisStart + SYNODIC_GAP, true);
|
||||
return nextStart - thisStart;
|
||||
|
@ -338,16 +342,26 @@ const UFieldResolutionTable* ChineseCalendar::getFieldResolutionTable() const {
|
|||
* day of the given month and year
|
||||
* @stable ICU 2.8
|
||||
*/
|
||||
int64_t ChineseCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const {
|
||||
int64_t ChineseCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
// If the month is out of range, adjust it into range, and
|
||||
// modify the extended year value accordingly.
|
||||
if (month < 0 || month > 11) {
|
||||
double m = month;
|
||||
eyear += (int32_t)ClockMath::floorDivide(m, 12.0, &m);
|
||||
if (uprv_add32_overflow(eyear, ClockMath::floorDivide(m, 12.0, &m), &eyear)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
month = (int32_t)m;
|
||||
}
|
||||
|
||||
int32_t gyear = eyear + fEpochYear - 1; // Gregorian year
|
||||
int32_t gyear;
|
||||
if (uprv_add32_overflow(eyear, fEpochYear - 1, &gyear)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
int32_t theNewYear = newYear(gyear);
|
||||
int32_t newMoon = newMoonNear(theNewYear + month * 29, true);
|
||||
|
||||
|
@ -358,13 +372,14 @@ int64_t ChineseCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, U
|
|||
|
||||
// Clone the calendar so we don't mess with the real one.
|
||||
LocalPointer<ChineseCalendar> work(clone());
|
||||
if (work.isNull())
|
||||
if (work.isNull()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
work->computeGregorianFields(julianDay, status);
|
||||
if (U_FAILURE(status))
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This will modify the MONTH and IS_LEAP_MONTH fields (only)
|
||||
work->computeChineseFields(newMoon, work->getGregorianYear(),
|
||||
|
@ -458,7 +473,11 @@ void ChineseCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode
|
|||
// Now do the standard roll computation on m, with the
|
||||
// allowed range of 0..n-1, where n is 12 or 13.
|
||||
int32_t n = hasLeapMonthBetweenWinterSolstices ? 13 : 12; // Months in this year
|
||||
int32_t newM = (m + amount) % n;
|
||||
if (uprv_add32_overflow(amount, m, &amount)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
int32_t newM = amount % n;
|
||||
if (newM < 0) {
|
||||
newM += n;
|
||||
}
|
||||
|
@ -986,7 +1005,10 @@ ChineseCalendar::setTemporalMonthCode(const char* code, UErrorCode& status )
|
|||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
|
||||
int32_t ChineseCalendar::internalGetMonth() const {
|
||||
int32_t ChineseCalendar::internalGetMonth(UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
if (resolveFields(kMonthPrecedence) == UCAL_MONTH) {
|
||||
return internalGet(UCAL_MONTH);
|
||||
}
|
||||
|
@ -996,24 +1018,29 @@ int32_t ChineseCalendar::internalGetMonth() const {
|
|||
temp->set(UCAL_DATE, 1);
|
||||
// Calculate the UCAL_MONTH and UCAL_IS_LEAP_MONTH by adding number of
|
||||
// months.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
temp->roll(UCAL_MONTH, internalGet(UCAL_ORDINAL_MONTH), status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ChineseCalendar *nonConstThis = (ChineseCalendar*)this; // cast away const
|
||||
nonConstThis->internalSet(UCAL_IS_LEAP_MONTH, temp->get(UCAL_IS_LEAP_MONTH, status));
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
int32_t month = temp->get(UCAL_MONTH, status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
nonConstThis->internalSet(UCAL_MONTH, month);
|
||||
return month;
|
||||
}
|
||||
|
||||
int32_t ChineseCalendar::internalGetMonth(int32_t defaultValue) const {
|
||||
int32_t ChineseCalendar::internalGetMonth(int32_t defaultValue, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
if (resolveFields(kMonthPrecedence) == UCAL_MONTH) {
|
||||
return internalGet(UCAL_MONTH, defaultValue);
|
||||
}
|
||||
return internalGetMonth();
|
||||
return internalGetMonth(status);
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -207,8 +207,8 @@ class U_I18N_API ChineseCalendar : public Calendar {
|
|||
|
||||
protected:
|
||||
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 handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override;
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth, UErrorCode& status) const override;
|
||||
virtual int32_t handleGetExtendedYear(UErrorCode& status) override;
|
||||
virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override;
|
||||
virtual const UFieldResolutionTable* getFieldResolutionTable() const override;
|
||||
|
@ -286,9 +286,9 @@ class U_I18N_API ChineseCalendar : public Calendar {
|
|||
virtual const char * getType() const override;
|
||||
|
||||
protected:
|
||||
virtual int32_t internalGetMonth(int32_t defaultValue) const override;
|
||||
virtual int32_t internalGetMonth(int32_t defaultValue, UErrorCode& status) const override;
|
||||
|
||||
virtual int32_t internalGetMonth() const override;
|
||||
virtual int32_t internalGetMonth(UErrorCode& status) const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
|
|
@ -51,6 +51,8 @@ U_NAMESPACE_BEGIN
|
|||
// Constructors...
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
const TimeZone* getDangiCalZoneAstroCalc(UErrorCode &status);
|
||||
|
||||
DangiCalendar::DangiCalendar(const Locale& aLocale, UErrorCode& success)
|
||||
: ChineseCalendar(aLocale, DANGI_EPOCH_YEAR, getDangiCalZoneAstroCalc(success), success)
|
||||
{
|
||||
|
@ -136,7 +138,7 @@ static void U_CALLCONV initDangiCalZoneAstroCalc(UErrorCode &status) {
|
|||
ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR, calendar_dangi_cleanup);
|
||||
}
|
||||
|
||||
const TimeZone* DangiCalendar::getDangiCalZoneAstroCalc(UErrorCode &status) const {
|
||||
const TimeZone* getDangiCalZoneAstroCalc(UErrorCode &status) {
|
||||
umtx_initOnce(gDangiCalendarInitOnce, &initDangiCalZoneAstroCalc, status);
|
||||
return gDangiCalendarZoneAstroCalc;
|
||||
}
|
||||
|
|
|
@ -88,8 +88,6 @@ class DangiCalendar : public ChineseCalendar {
|
|||
|
||||
private:
|
||||
|
||||
const TimeZone* getDangiCalZoneAstroCalc(UErrorCode &status) const;
|
||||
|
||||
// UObject stuff
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -70,7 +70,12 @@ EthiopicCalendar::handleGetExtendedYear(UErrorCode& status)
|
|||
if (internalGet(UCAL_ERA, AMETE_MIHRET) == AMETE_MIHRET) {
|
||||
return internalGet(UCAL_YEAR, 1); // Default to year 1
|
||||
}
|
||||
return internalGet(UCAL_YEAR, 1) - AMETE_MIHRET_DELTA;
|
||||
int32_t year = internalGet(UCAL_YEAR, 1);
|
||||
if (uprv_add32_overflow(year, -AMETE_MIHRET_DELTA, &year)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
return year;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -194,8 +199,13 @@ EthiopicAmeteAlemCalendar::handleGetExtendedYear(UErrorCode& status)
|
|||
if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
|
||||
return internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1
|
||||
}
|
||||
return internalGet(UCAL_YEAR, 1 + AMETE_MIHRET_DELTA)
|
||||
- AMETE_MIHRET_DELTA; // Default to year 1 of Amelete Mihret
|
||||
// Default to year 1 of Amelete Mihret
|
||||
int32_t year = internalGet(UCAL_YEAR, 1 + AMETE_MIHRET_DELTA);
|
||||
if (uprv_add32_overflow(year, -AMETE_MIHRET_DELTA, &year)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
return year;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -538,14 +538,21 @@ int32_t GregorianCalendar::handleComputeJulianDay(UCalendarDateFields bestField,
|
|||
|
||||
int64_t GregorianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
|
||||
|
||||
UBool /* useMonth */) const
|
||||
UBool /* useMonth */, UErrorCode& status) const
|
||||
{
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
GregorianCalendar *nonConstThis = (GregorianCalendar*)this; // cast away const
|
||||
|
||||
// If the month is out of range, adjust it into range, and
|
||||
// modify the extended year value accordingly.
|
||||
if (month < 0 || month > 11) {
|
||||
eyear += ClockMath::floorDivide(month, 12, &month);
|
||||
if (uprv_add32_overflow(ClockMath::floorDivide(month, 12, &month),
|
||||
eyear, &eyear)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
UBool isLeap = eyear%4 == 0;
|
||||
|
@ -584,7 +591,7 @@ int64_t GregorianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
|
|||
return julianDay;
|
||||
}
|
||||
|
||||
int32_t GregorianCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const
|
||||
int32_t GregorianCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& /* status */) const
|
||||
{
|
||||
// If the month is out of range, adjust it into range, and
|
||||
// modify the extended year value accordingly.
|
||||
|
@ -601,10 +608,10 @@ int32_t GregorianCalendar::handleGetYearLength(int32_t eyear) const {
|
|||
|
||||
|
||||
int32_t
|
||||
GregorianCalendar::monthLength(int32_t month) const
|
||||
GregorianCalendar::monthLength(int32_t month, UErrorCode& status) const
|
||||
{
|
||||
int32_t year = internalGet(UCAL_EXTENDED_YEAR);
|
||||
return handleGetMonthLength(year, month);
|
||||
return handleGetMonthLength(year, month, status);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -641,10 +648,12 @@ GregorianCalendar::validateFields() const
|
|||
// specially.
|
||||
if (isSet(UCAL_DATE)) {
|
||||
int32_t date = internalGet(UCAL_DATE);
|
||||
UErrorCode internalStatus = U_ZERO_ERROR;
|
||||
if (date < getMinimum(UCAL_DATE) ||
|
||||
date > monthLength(internalGetMonth())) {
|
||||
date > monthLength(internalGetMonth(internalStatus), internalStatus) ||
|
||||
U_FAILURE(internalStatus)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isSet(UCAL_DAY_OF_YEAR)) {
|
||||
|
@ -821,7 +830,10 @@ GregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& s
|
|||
case UCAL_DAY_OF_MONTH:
|
||||
case UCAL_WEEK_OF_MONTH:
|
||||
{
|
||||
int32_t max = monthLength(internalGetMonth());
|
||||
int32_t max = monthLength(internalGetMonth(status), status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
UDate t = internalGetTime();
|
||||
// We subtract 1 from the DAY_OF_MONTH to make it zero-based, and an
|
||||
// additional 10 if we are after the cutover. Thus the monthStart
|
||||
|
@ -854,7 +866,11 @@ GregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& s
|
|||
// may be one year before or after the calendar year.
|
||||
int32_t isoYear = get(UCAL_YEAR_WOY, status);
|
||||
int32_t isoDoy = internalGet(UCAL_DAY_OF_YEAR);
|
||||
if (internalGetMonth() == UCAL_JANUARY) {
|
||||
int32_t month = internalGetMonth(status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (month == UCAL_JANUARY) {
|
||||
if (woy >= 52) {
|
||||
isoDoy += handleGetYearLength(isoYear);
|
||||
}
|
||||
|
@ -1197,7 +1213,11 @@ int32_t GregorianCalendar::handleGetExtendedYear(UErrorCode& status) {
|
|||
break;
|
||||
|
||||
case UCAL_YEAR_WOY:
|
||||
year = handleGetExtendedYearFromWeekFields(internalGet(UCAL_YEAR_WOY), internalGet(UCAL_WEEK_OF_YEAR));
|
||||
year = handleGetExtendedYearFromWeekFields(
|
||||
internalGet(UCAL_YEAR_WOY), internalGet(UCAL_WEEK_OF_YEAR), status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
#if defined (U_DEBUG_CAL)
|
||||
// if(internalGet(UCAL_YEAR_WOY) != year) {
|
||||
fprintf(stderr, "%s:%d: hGEYFWF[%d,%d] -> %d\n",
|
||||
|
@ -1212,14 +1232,17 @@ int32_t GregorianCalendar::handleGetExtendedYear(UErrorCode& status) {
|
|||
return year;
|
||||
}
|
||||
|
||||
int32_t GregorianCalendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy)
|
||||
int32_t GregorianCalendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy, UErrorCode& status)
|
||||
{
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
// convert year to extended form
|
||||
int32_t era = internalGet(UCAL_ERA, AD);
|
||||
if(era == BC) {
|
||||
yearWoy = 1 - yearWoy;
|
||||
}
|
||||
return Calendar::handleGetExtendedYearFromWeekFields(yearWoy, woy);
|
||||
return Calendar::handleGetExtendedYearFromWeekFields(yearWoy, woy, status);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -508,7 +508,7 @@ int32_t HebrewCalendar::handleGetLimit(UCalendarDateFields field, ELimitType lim
|
|||
* Returns the length of the given month in the given year
|
||||
* @internal
|
||||
*/
|
||||
int32_t HebrewCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
|
||||
int32_t HebrewCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& /* status */) const {
|
||||
// Resolve out-of-range months. This is necessary in order to
|
||||
// obtain the correct year. We correct to
|
||||
// a 12- or 13-month year (add/subtract 12 or 13, depending
|
||||
|
@ -546,7 +546,7 @@ 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(status)) && internalGetMonth() == ADAR_1) {
|
||||
&& !isLeapYear(handleGetExtendedYear(status)) && internalGetMonth(status) == ADAR_1) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
@ -656,8 +656,11 @@ int32_t HebrewCalendar::handleGetExtendedYear(UErrorCode& status ) {
|
|||
* Return JD of start of given month/year.
|
||||
* @internal
|
||||
*/
|
||||
int64_t HebrewCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /*useMonth*/) const {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int64_t HebrewCalendar::handleComputeMonthStart(
|
||||
int32_t eyear, int32_t month, UBool /*useMonth*/, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
// Resolve out-of-range months. This is necessary in order to
|
||||
// obtain the correct year. We correct to
|
||||
// a 12- or 13-month year (add/subtract 12 or 13, depending
|
||||
|
@ -665,11 +668,19 @@ int64_t HebrewCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UB
|
|||
// the leap year determines whether or not month 5 (Adar 1)
|
||||
// is present, we allow 0..12 in any given year.
|
||||
while (month < 0) {
|
||||
month += monthsInYear(--eyear);
|
||||
if (uprv_add32_overflow(eyear, -1, &eyear) ||
|
||||
uprv_add32_overflow(month, monthsInYear(eyear), &month)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Careful: allow 0..12 in all years
|
||||
while (month > 12) {
|
||||
month -= monthsInYear(eyear++);
|
||||
if (uprv_add32_overflow(month, -monthsInYear(eyear), &month) ||
|
||||
uprv_add32_overflow(eyear, 1, &eyear)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t day = startOfYear(eyear, status);
|
||||
|
@ -784,17 +795,26 @@ void HebrewCalendar::setTemporalMonthCode(const char* code, UErrorCode& status )
|
|||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
|
||||
int32_t HebrewCalendar::internalGetMonth() const {
|
||||
int32_t HebrewCalendar::internalGetMonth(UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
if (resolveFields(kMonthPrecedence) == UCAL_ORDINAL_MONTH) {
|
||||
int32_t ordinalMonth = internalGet(UCAL_ORDINAL_MONTH);
|
||||
HebrewCalendar *nonConstThis = (HebrewCalendar*)this; // cast away const
|
||||
|
||||
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);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
if (isLeapYear(year) || ordinalMonth <= ADAR_1) {
|
||||
return ordinalMonth;
|
||||
}
|
||||
if (!uprv_add32_overflow(ordinalMonth, 1, &ordinalMonth)) {
|
||||
return ordinalMonth;
|
||||
}
|
||||
}
|
||||
return Calendar::internalGetMonth();
|
||||
return Calendar::internalGetMonth(status);
|
||||
}
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(HebrewCalendar)
|
||||
|
|
|
@ -319,7 +319,7 @@ public:
|
|||
* implementation than the default implementation in Calendar.
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override;
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given extended year of this
|
||||
|
@ -369,7 +369,7 @@ public:
|
|||
* @internal
|
||||
*/
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month,
|
||||
UBool useMonth) const override;
|
||||
UBool useMonth, UErrorCode& status) const override;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -443,7 +443,7 @@ public:
|
|||
virtual void setTemporalMonthCode(const char* code, UErrorCode& status ) override;
|
||||
|
||||
protected:
|
||||
virtual int32_t internalGetMonth() const override;
|
||||
virtual int32_t internalGetMonth(UErrorCode& status) const override;
|
||||
|
||||
private: // Calendar-specific implementation
|
||||
/**
|
||||
|
|
|
@ -108,7 +108,7 @@ static UBool isGregorianLeap(int32_t year)
|
|||
* @param eyear The year in Saka Era
|
||||
* @param month The month(0-based) in Indian calendar
|
||||
*/
|
||||
int32_t IndianCalendar::handleGetMonthLength(int32_t eyear, int32_t month) const {
|
||||
int32_t IndianCalendar::handleGetMonthLength(int32_t eyear, int32_t month, UErrorCode& /* status */) const {
|
||||
if (month < 0 || month > 11) {
|
||||
eyear += ClockMath::floorDivide(month, 12, &month);
|
||||
}
|
||||
|
@ -203,14 +203,20 @@ static double IndianToJD(int32_t year, int32_t month, int32_t date) {
|
|||
* @param eyear The year in Indian Calendar measured from Saka Era (78 AD).
|
||||
* @param month The month in Indian calendar
|
||||
*/
|
||||
int64_t IndianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /* useMonth */ ) const {
|
||||
int64_t IndianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /* useMonth */, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//month is 0 based; converting it to 1-based
|
||||
int32_t imonth;
|
||||
|
||||
// If the month is out of range, adjust it into range, and adjust the extended year accordingly
|
||||
if (month < 0 || month > 11) {
|
||||
eyear += (int32_t)ClockMath::floorDivide(month, 12, &month);
|
||||
if (uprv_add32_overflow(eyear, ClockMath::floorDivide(month, 12, &month), &eyear)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(month == 12){
|
||||
|
|
|
@ -209,7 +209,7 @@ public:
|
|||
* @param year The month(0-based) in Indian year
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override;
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given Indian year
|
||||
|
@ -225,7 +225,7 @@ public:
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const override;
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth, UErrorCode& status) const override;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Functions for converting from milliseconds to field values
|
||||
|
|
|
@ -321,8 +321,19 @@ int64_t IslamicCalendar::yearStart(int32_t year) const{
|
|||
* @param year The hijri year
|
||||
* @param month The hijri month, 0-based (assumed to be in range 0..11)
|
||||
*/
|
||||
int64_t IslamicCalendar::monthStart(int32_t year, int32_t month) const {
|
||||
return trueMonthStart(12*(year-1) + month);
|
||||
int64_t IslamicCalendar::monthStart(int32_t year, int32_t month, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
int32_t temp;
|
||||
if (uprv_add32_overflow(year, -1, &temp) ||
|
||||
uprv_mul32_overflow(temp, 12, &temp) ||
|
||||
uprv_add32_overflow(temp, month, &month)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return trueMonthStart(month);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -427,7 +438,8 @@ double IslamicCalendar::moonAge(UDate time, UErrorCode &status)
|
|||
* @param year The hijri month, 0-based
|
||||
* @draft ICU 2.4
|
||||
*/
|
||||
int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
|
||||
int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month,
|
||||
UErrorCode& /* status */) const {
|
||||
month = 12*(extendedYear-1) + month;
|
||||
return trueMonthStart(month+1) - trueMonthStart(month) ;
|
||||
}
|
||||
|
@ -453,18 +465,30 @@ int32_t IslamicCalendar::handleGetYearLength(int32_t extendedYear) const {
|
|||
/**
|
||||
* @draft ICU 2.4
|
||||
*/
|
||||
int64_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /* useMonth */) const {
|
||||
int64_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
|
||||
UBool /* useMonth */,
|
||||
UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
// This may be called by Calendar::handleComputeJulianDay with months out of the range
|
||||
// 0..11. Need to handle that here since monthStart requires months in the range 0.11.
|
||||
if (month > 11) {
|
||||
eyear += (month / 12);
|
||||
if (uprv_add32_overflow(eyear, (month / 12), &eyear)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
month %= 12;
|
||||
} else if (month < 0) {
|
||||
month++;
|
||||
eyear += (month / 12) - 1;
|
||||
if (uprv_add32_overflow(eyear, (month / 12) - 1, &eyear)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
month = (month % 12) + 11;
|
||||
}
|
||||
return monthStart(eyear, month) + getEpoc() - 1;
|
||||
return monthStart(eyear, month, status) + getEpoc() - 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -531,14 +555,20 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status)
|
|||
|
||||
int32_t year = month >= 0 ? ((month / 12) + 1) : ((month + 1 ) / 12);
|
||||
month = ((month % 12) + 12 ) % 12;
|
||||
int64_t dayOfMonth = (days - monthStart(year, month)) + 1;
|
||||
int64_t dayOfMonth = (days - monthStart(year, month, status)) + 1;
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (dayOfMonth > INT32_MAX || dayOfMonth < INT32_MIN) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// Now figure out the day of the year.
|
||||
int64_t dayOfYear = (days - monthStart(year, 0)) + 1;
|
||||
int64_t dayOfYear = (days - monthStart(year, 0, status)) + 1;
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (dayOfYear > INT32_MAX || dayOfYear < INT32_MIN) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
|
@ -697,10 +727,10 @@ int64_t IslamicCivilCalendar::yearStart(int32_t year) const{
|
|||
* @param year The hijri year
|
||||
* @param month The hijri month, 0-based (assumed to be in range 0..11)
|
||||
*/
|
||||
int64_t IslamicCivilCalendar::monthStart(int32_t year, int32_t month) const {
|
||||
int64_t IslamicCivilCalendar::monthStart(int32_t year, int32_t month, UErrorCode& /*status*/) const {
|
||||
// This does not handle months out of the range 0..11
|
||||
return static_cast<int64_t>(
|
||||
uprv_ceil(29.5*month) + 354LL*(year-1) +
|
||||
uprv_ceil(29.5*month) + 354LL*(year-1LL) +
|
||||
ClockMath::floorDivideInt64(
|
||||
11LL*static_cast<int64_t>(year) + 3LL, 30LL));
|
||||
}
|
||||
|
@ -712,7 +742,8 @@ int64_t IslamicCivilCalendar::monthStart(int32_t year, int32_t month) const {
|
|||
* @param year The hijri month, 0-based
|
||||
* @draft ICU 2.4
|
||||
*/
|
||||
int32_t IslamicCivilCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
|
||||
int32_t IslamicCivilCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month,
|
||||
UErrorCode& /* status */) const {
|
||||
int32_t length = 29 + (month+1) % 2;
|
||||
if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
|
||||
length++;
|
||||
|
@ -755,14 +786,20 @@ void IslamicCivilCalendar::handleComputeFields(int32_t julianDay, UErrorCode &st
|
|||
uprv_ceil((days - 29 - yearStart(year)) / 29.5 ));
|
||||
month = month<11?month:11;
|
||||
|
||||
int64_t dayOfMonth = (days - monthStart(year, month)) + 1;
|
||||
int64_t dayOfMonth = (days - monthStart(year, month, status)) + 1;
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (dayOfMonth > INT32_MAX || dayOfMonth < INT32_MIN) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// Now figure out the day of the year.
|
||||
int64_t dayOfYear = (days - monthStart(year, 0)) + 1;
|
||||
int64_t dayOfYear = (days - monthStart(year, 0, status)) + 1;
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (dayOfYear > INT32_MAX || dayOfYear < INT32_MIN) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
|
@ -826,7 +863,7 @@ IslamicUmalquraCalendar* IslamicUmalquraCalendar::clone() const {
|
|||
*/
|
||||
int64_t IslamicUmalquraCalendar::yearStart(int32_t year) const {
|
||||
if (year < UMALQURA_YEAR_START || year > UMALQURA_YEAR_END) {
|
||||
return 354LL * (year-1) +
|
||||
return 354LL * (year-1LL) +
|
||||
ClockMath::floorDivideInt64((11LL*year+3LL), 30LL);
|
||||
}
|
||||
year -= UMALQURA_YEAR_START;
|
||||
|
@ -844,10 +881,16 @@ int64_t IslamicUmalquraCalendar::yearStart(int32_t year) const {
|
|||
* @param year The hijri year
|
||||
* @param month The hijri month, 0-based (assumed to be in range 0..11)
|
||||
*/
|
||||
int64_t IslamicUmalquraCalendar::monthStart(int32_t year, int32_t month) const {
|
||||
int64_t IslamicUmalquraCalendar::monthStart(int32_t year, int32_t month, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
int64_t ms = yearStart(year);
|
||||
for(int i=0; i< month; i++){
|
||||
ms+= handleGetMonthLength(year, i);
|
||||
ms+= handleGetMonthLength(year, i, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ms;
|
||||
}
|
||||
|
@ -858,7 +901,8 @@ int64_t IslamicUmalquraCalendar::monthStart(int32_t year, int32_t month) const {
|
|||
* @param year The hijri year
|
||||
* @param year The hijri month, 0-based
|
||||
*/
|
||||
int32_t IslamicUmalquraCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
|
||||
int32_t IslamicUmalquraCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month,
|
||||
UErrorCode& /* status */) const {
|
||||
int32_t length = 0;
|
||||
if (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END) {
|
||||
length = 29 + (month+1) % 2;
|
||||
|
@ -880,9 +924,11 @@ int32_t IslamicUmalquraCalendar::handleGetYearLength(int32_t extendedYear) const
|
|||
return 354 + (civilLeapYear(extendedYear) ? 1 : 0);
|
||||
}
|
||||
int len = 0;
|
||||
UErrorCode internalStatus = U_ZERO_ERROR;
|
||||
for(int i=0; i<12; i++) {
|
||||
len += handleGetMonthLength(extendedYear, i);
|
||||
len += handleGetMonthLength(extendedYear, i, internalStatus);
|
||||
}
|
||||
U_ASSERT(U_SUCCESS(internalStatus));
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -933,10 +979,13 @@ void IslamicUmalquraCalendar::handleComputeFields(int32_t julianDay, UErrorCode
|
|||
break;
|
||||
}
|
||||
if (d < yearLength){
|
||||
int32_t monthLen = handleGetMonthLength(year, month);
|
||||
int32_t monthLen = handleGetMonthLength(year, month, status);
|
||||
for (month = 0;
|
||||
d > monthLen;
|
||||
monthLen = handleGetMonthLength(year, ++month)) {
|
||||
monthLen = handleGetMonthLength(year, ++month, status)) {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
d -= monthLen;
|
||||
}
|
||||
break;
|
||||
|
@ -944,14 +993,20 @@ void IslamicUmalquraCalendar::handleComputeFields(int32_t julianDay, UErrorCode
|
|||
}
|
||||
}
|
||||
|
||||
dayOfMonth = (days - monthStart(year, month)) + 1;
|
||||
dayOfMonth = (days - monthStart(year, month, status)) + 1;
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (dayOfMonth > INT32_MAX || dayOfMonth < INT32_MIN) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// Now figure out the day of the year.
|
||||
dayOfYear = (days - monthStart(year, 0)) + 1;
|
||||
dayOfYear = (days - monthStart(year, 0, status)) + 1;
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (dayOfYear > INT32_MAX || dayOfYear < INT32_MIN) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
|
|
|
@ -210,7 +210,7 @@ class U_I18N_API IslamicCalendar : public Calendar {
|
|||
* @param year The hijri year
|
||||
* @param year The hijri month, 0-based
|
||||
*/
|
||||
virtual int64_t monthStart(int32_t year, int32_t month) const;
|
||||
virtual int64_t monthStart(int32_t year, int32_t month, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Find the day number on which a particular month of the true/lunar
|
||||
|
@ -250,7 +250,7 @@ class U_I18N_API IslamicCalendar : public Calendar {
|
|||
* @param year The hijri month, 0-based
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override;
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given Islamic year
|
||||
|
@ -266,7 +266,7 @@ class U_I18N_API IslamicCalendar : public Calendar {
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const override;
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth, UErrorCode& status) const override;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Functions for converting from milliseconds to field values
|
||||
|
@ -468,7 +468,7 @@ class U_I18N_API IslamicCivilCalendar : public IslamicCalendar {
|
|||
* @param year The hijri month, 0-based
|
||||
* @internal
|
||||
*/
|
||||
virtual int64_t monthStart(int32_t year, int32_t month) const override;
|
||||
virtual int64_t monthStart(int32_t year, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the length (in days) of the given month.
|
||||
|
@ -477,7 +477,7 @@ class U_I18N_API IslamicCivilCalendar : public IslamicCalendar {
|
|||
* @param year The hijri month, 0-based
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override;
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given Islamic year
|
||||
|
@ -651,7 +651,7 @@ class U_I18N_API IslamicUmalquraCalendar : public IslamicCalendar {
|
|||
* @param year The hijri month, 0-based
|
||||
* @internal
|
||||
*/
|
||||
virtual int64_t monthStart(int32_t year, int32_t month) const override;
|
||||
virtual int64_t monthStart(int32_t year, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the length (in days) of the given month.
|
||||
|
@ -660,7 +660,7 @@ class U_I18N_API IslamicUmalquraCalendar : public IslamicCalendar {
|
|||
* @param year The hijri month, 0-based
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override;
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given Islamic year
|
||||
|
|
|
@ -146,8 +146,11 @@ const char *JapaneseCalendar::getType() const
|
|||
return "japanese";
|
||||
}
|
||||
|
||||
int32_t JapaneseCalendar::getDefaultMonthInYear(int32_t eyear)
|
||||
int32_t JapaneseCalendar::getDefaultMonthInYear(int32_t eyear, UErrorCode& status)
|
||||
{
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
int32_t era = internalGetEra();
|
||||
// TODO do we assume we can trust 'era'? What if it is denormalized?
|
||||
|
||||
|
@ -155,9 +158,10 @@ int32_t JapaneseCalendar::getDefaultMonthInYear(int32_t eyear)
|
|||
|
||||
// Find out if we are at the edge of an era
|
||||
int32_t eraStart[3] = { 0,0,0 };
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
gJapaneseEraRules->getStartDate(era, eraStart, status);
|
||||
U_ASSERT(U_SUCCESS(status));
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
if(eyear == eraStart[0]) {
|
||||
// Yes, we're in the first year of this era.
|
||||
return eraStart[1] // month
|
||||
|
@ -210,9 +214,12 @@ int32_t JapaneseCalendar::handleGetExtendedYear(UErrorCode& status)
|
|||
}
|
||||
|
||||
// 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)
|
||||
+ eraStartYear // add gregorian starting year
|
||||
- 1; // Subtract one because year starts at 1
|
||||
year = internalGet(UCAL_YEAR, 1); // pin to minimum of year 1 (first year)
|
||||
// add gregorian starting year, subtract one because year starts at 1
|
||||
if (uprv_add32_overflow(year, eraStartYear - 1, &year)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return year;
|
||||
}
|
||||
|
@ -223,7 +230,7 @@ void JapaneseCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status
|
|||
//Calendar::timeToFields(theTime, quick, status);
|
||||
GregorianCalendar::handleComputeFields(julianDay, status);
|
||||
int32_t year = internalGet(UCAL_EXTENDED_YEAR); // Gregorian year
|
||||
int32_t eraIdx = gJapaneseEraRules->getEraIndex(year, internalGetMonth() + 1, internalGet(UCAL_DAY_OF_MONTH), status);
|
||||
int32_t eraIdx = gJapaneseEraRules->getEraIndex(year, internalGetMonth(status) + 1, internalGet(UCAL_DAY_OF_MONTH), status);
|
||||
|
||||
internalSet(UCAL_ERA, eraIdx);
|
||||
internalSet(UCAL_YEAR, year - gJapaneseEraRules->getStartYear(eraIdx, status) + 1);
|
||||
|
|
|
@ -212,7 +212,7 @@ protected:
|
|||
* @param eyear the extended year
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t getDefaultMonthInYear(int32_t eyear) override;
|
||||
virtual int32_t getDefaultMonthInYear(int32_t eyear, UErrorCode& status) override;
|
||||
|
||||
/***
|
||||
* Called by computeJulianDay. Returns the default day (1-based) for the month,
|
||||
|
|
|
@ -111,17 +111,16 @@ int32_t PersianCalendar::handleGetLimit(UCalendarDateFields field, ELimitType li
|
|||
*/
|
||||
UBool PersianCalendar::isLeapYear(int32_t year)
|
||||
{
|
||||
int32_t remainder;
|
||||
ClockMath::floorDivide(25 * year + 11, 33, &remainder);
|
||||
return (remainder < 8);
|
||||
int64_t y = static_cast<int64_t>(year) * 25LL + 11LL;
|
||||
return (y % 33L < 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the day # on which the given year starts. Days are counted
|
||||
* from the Persian epoch, origin 0.
|
||||
*/
|
||||
int32_t PersianCalendar::yearStart(int32_t year) {
|
||||
return handleComputeMonthStart(year,0,false);
|
||||
int32_t PersianCalendar::yearStart(int32_t year, UErrorCode& status) {
|
||||
return handleComputeMonthStart(year,0,false, status);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,8 +130,8 @@ int32_t PersianCalendar::yearStart(int32_t year) {
|
|||
* @param year The Persian year
|
||||
* @param year The Persian month, 0-based
|
||||
*/
|
||||
int32_t PersianCalendar::monthStart(int32_t year, int32_t month) const {
|
||||
return handleComputeMonthStart(year,month,true);
|
||||
int32_t PersianCalendar::monthStart(int32_t year, int32_t month, UErrorCode& status) const {
|
||||
return handleComputeMonthStart(year,month,true, status);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -145,7 +144,7 @@ int32_t PersianCalendar::monthStart(int32_t year, int32_t month) const {
|
|||
* @param year The Persian year
|
||||
* @param year The Persian month, 0-based
|
||||
*/
|
||||
int32_t PersianCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
|
||||
int32_t PersianCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& /*status*/) const {
|
||||
// If the month is out of range, adjust it into range, and
|
||||
// modify the extended year value accordingly.
|
||||
if (month < 0 || month > 11) {
|
||||
|
@ -167,14 +166,20 @@ int32_t PersianCalendar::handleGetYearLength(int32_t extendedYear) const {
|
|||
//-------------------------------------------------------------------------
|
||||
|
||||
// Return JD of start of given month/year
|
||||
int64_t PersianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /*useMonth*/) const {
|
||||
int64_t PersianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /*useMonth*/, UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
// If the month is out of range, adjust it into range, and
|
||||
// modify the extended year value accordingly.
|
||||
if (month < 0 || month > 11) {
|
||||
eyear += ClockMath::floorDivide(month, 12, &month);
|
||||
if (uprv_add32_overflow(eyear, ClockMath::floorDivide(month, 12, &month), &eyear)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t julianDay = PERSIAN_EPOCH - 1 + 365LL * (eyear - 1) + ClockMath::floorDivide(8LL * eyear + 21, 33);
|
||||
int64_t julianDay = PERSIAN_EPOCH - 1LL + 365LL * (eyear - 1LL) + ClockMath::floorDivide(8LL * eyear + 21, 33);
|
||||
|
||||
if (month != 0) {
|
||||
julianDay += kPersianNumDays[month];
|
||||
|
|
|
@ -176,7 +176,7 @@ class PersianCalendar : public Calendar {
|
|||
* Return the day # on which the given year starts. Days are counted
|
||||
* from the Hijri epoch, origin 0.
|
||||
*/
|
||||
int32_t yearStart(int32_t year);
|
||||
int32_t yearStart(int32_t year, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Return the day # on which the given month starts. Days are counted
|
||||
|
@ -185,7 +185,7 @@ class PersianCalendar : public Calendar {
|
|||
* @param year The hijri shamsi year
|
||||
* @param year The hijri shamsi month, 0-based
|
||||
*/
|
||||
int32_t monthStart(int32_t year, int32_t month) const;
|
||||
int32_t monthStart(int32_t year, int32_t month, UErrorCode& status) const;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Calendar framework
|
||||
|
@ -203,7 +203,7 @@ class PersianCalendar : public Calendar {
|
|||
* @param year The hijri shamsi month, 0-based
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override;
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given Persian year
|
||||
|
@ -219,7 +219,7 @@ class PersianCalendar : public Calendar {
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const override;
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth, UErrorCode& status) const override;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Functions for converting from milliseconds to field values
|
||||
|
|
|
@ -519,7 +519,12 @@ SimpleTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingT
|
|||
|
||||
rawOffsetGMT = getRawOffset();
|
||||
int32_t year, month, dom, dow, millis;
|
||||
int32_t day = ClockMath::floorDivide(date, U_MILLIS_PER_DAY, &millis);
|
||||
double dday = ClockMath::floorDivide(date, U_MILLIS_PER_DAY, &millis);
|
||||
if (dday > INT32_MAX || dday < INT32_MIN) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
int32_t day = dday;
|
||||
|
||||
Grego::dayToFields(day, year, month, dom, dow);
|
||||
|
||||
|
|
|
@ -78,10 +78,17 @@ int32_t TaiwanCalendar::handleGetExtendedYear(UErrorCode& status)
|
|||
year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch);
|
||||
} else {
|
||||
int32_t era = internalGet(UCAL_ERA, MINGUO);
|
||||
year = internalGet(UCAL_YEAR, 1);
|
||||
if(era == MINGUO) {
|
||||
year = internalGet(UCAL_YEAR, 1) + kTaiwanEraStart;
|
||||
if (uprv_add32_overflow(year, kTaiwanEraStart, &year)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
} else if(era == BEFORE_MINGUO) {
|
||||
year = 1 - internalGet(UCAL_YEAR, 1) + kTaiwanEraStart;
|
||||
if (uprv_add32_overflow(1 + kTaiwanEraStart, -year, &year)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
|
|
|
@ -1558,7 +1558,7 @@ protected:
|
|||
* @return The value for the UCAL_MONTH.
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t internalGetMonth() const;
|
||||
virtual int32_t internalGetMonth(UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Use this function instead of internalGet(UCAL_MONTH, defaultValue). The implementation
|
||||
|
@ -1568,10 +1568,12 @@ protected:
|
|||
*
|
||||
* @param defaultValue a default value used if the UCAL_MONTH and
|
||||
* UCAL_ORDINAL are both unset.
|
||||
* @param status Output param set to failure code on function return
|
||||
* when this function fails.
|
||||
* @return The value for the UCAL_MONTH.
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t internalGetMonth(int32_t defaultValue) const;
|
||||
virtual int32_t internalGetMonth(int32_t defaultValue, UErrorCode& status) const;
|
||||
|
||||
#ifndef U_HIDE_DEPRECATED_API
|
||||
/**
|
||||
|
@ -1660,12 +1662,14 @@ protected:
|
|||
* @param useMonth if false, compute the day before the first day of
|
||||
* the given year, otherwise, compute the day before the first day of
|
||||
* the given month
|
||||
* @param status Output param set to failure code on function return
|
||||
* when this function fails.
|
||||
* @return the Julian day number of the day before the first
|
||||
* day of the given month and year
|
||||
* @internal
|
||||
*/
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month,
|
||||
UBool useMonth) const = 0;
|
||||
UBool useMonth, UErrorCode& status) const = 0;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given month of the given extended
|
||||
|
@ -1674,7 +1678,7 @@ protected:
|
|||
* implementation than the default implementation in Calendar.
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const ;
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const ;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given extended year of this
|
||||
|
@ -1716,7 +1720,7 @@ protected:
|
|||
* @return the extended year, UCAL_EXTENDED_YEAR
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy);
|
||||
virtual int32_t handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Validate a single field of this calendar. Subclasses should
|
||||
|
@ -2022,9 +2026,11 @@ protected:
|
|||
* Called by computeJulianDay. Returns the default month (0-based) for the year,
|
||||
* taking year and era into account. Defaults to 0 for Gregorian, which doesn't care.
|
||||
* @param eyear The extended year
|
||||
* @param status Output param set to failure code on function return
|
||||
* when this function fails.
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t getDefaultMonthInYear(int32_t eyear) ;
|
||||
virtual int32_t getDefaultMonthInYear(int32_t eyear, UErrorCode& status);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -2155,7 +2161,7 @@ protected:
|
|||
* returns the local DOW, valid range 0..6
|
||||
* @internal
|
||||
*/
|
||||
int32_t getLocalDOW();
|
||||
int32_t getLocalDOW(UErrorCode& status);
|
||||
#endif /* U_HIDE_INTERNAL_API */
|
||||
|
||||
private:
|
||||
|
|
|
@ -483,12 +483,13 @@ public:
|
|||
* @param useMonth if false, compute the day before the first day of
|
||||
* the given year, otherwise, compute the day before the first day of
|
||||
* the given month
|
||||
* @param status Fill-in parameter which receives the status of this operation.
|
||||
* @return the Julian day number of the day before the first
|
||||
* day of the given month and year
|
||||
* @internal
|
||||
*/
|
||||
virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month,
|
||||
UBool useMonth) const override;
|
||||
UBool useMonth, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Subclasses may override this. This method calls
|
||||
|
@ -508,7 +509,7 @@ public:
|
|||
* implementation than the default implementation in Calendar.
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override;
|
||||
virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override;
|
||||
|
||||
/**
|
||||
* Return the number of days in the given extended year of this
|
||||
|
@ -522,10 +523,11 @@ public:
|
|||
/**
|
||||
* return the length of the given month.
|
||||
* @param month the given month.
|
||||
* @param status Fill-in parameter which receives the status of this operation.
|
||||
* @return the length of the given month.
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t monthLength(int32_t month) const;
|
||||
virtual int32_t monthLength(int32_t month, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* return the length of the month according to the given year.
|
||||
|
@ -597,7 +599,7 @@ public:
|
|||
* @return the extended year, UCAL_EXTENDED_YEAR
|
||||
* @internal
|
||||
*/
|
||||
virtual int32_t handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy) override;
|
||||
virtual int32_t handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy, UErrorCode& status) override;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -197,6 +197,7 @@ void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
|
|||
TESTCASE_AUTO(Test22633PersianOverflow);
|
||||
TESTCASE_AUTO(Test22633HebrewOverflow);
|
||||
TESTCASE_AUTO(Test22633AMPMOverflow);
|
||||
TESTCASE_AUTO(Test22633SetGetTimeOverflow);
|
||||
|
||||
TESTCASE_AUTO(TestAddOverflow);
|
||||
|
||||
|
@ -5719,6 +5720,56 @@ void CalendarTest::Test22633AMPMOverflow() {
|
|||
assertTrue("Should return success", U_SUCCESS(status));
|
||||
}
|
||||
|
||||
void CalendarTest::Test22633SetGetTimeOverflow() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Locale locale = Locale::getEnglish();
|
||||
LocalPointer<StringEnumeration> values(
|
||||
Calendar::getKeywordValuesForLocale("calendar", locale, false, status),
|
||||
status);
|
||||
assertTrue("Should return success", U_SUCCESS(status));
|
||||
if (U_SUCCESS(status)) {
|
||||
const char* value = nullptr;
|
||||
while ((value = values->next(nullptr, status)) != nullptr && U_SUCCESS(status)) {
|
||||
bool isHebrew = strcmp("hebrew", value) == 0;
|
||||
locale.setKeywordValue("calendar", value, status);
|
||||
assertTrue("Should return success", U_SUCCESS(status));
|
||||
|
||||
LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), locale, status), status);
|
||||
assertTrue("Should return success", U_SUCCESS(status));
|
||||
|
||||
assertTrue("Should return success", U_SUCCESS(status));
|
||||
for (int32_t i = 0; i < UCAL_FIELD_COUNT; i++) {
|
||||
status = U_ZERO_ERROR;
|
||||
cal->clear();
|
||||
cal->set(static_cast<UCalendarDateFields>(i), INT32_MAX);
|
||||
cal->getTime(status);
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
cal->clear();
|
||||
cal->set(static_cast<UCalendarDateFields>(i), INT32_MIN);
|
||||
cal->getTime(status);
|
||||
|
||||
if (!isHebrew) {
|
||||
for (int32_t j = 0; j < UCAL_FIELD_COUNT; j++) {
|
||||
status = U_ZERO_ERROR;
|
||||
cal->clear();
|
||||
cal->set(static_cast<UCalendarDateFields>(i), INT32_MAX);
|
||||
cal->set(static_cast<UCalendarDateFields>(j), INT32_MAX);
|
||||
cal->getTime(status);
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
cal->clear();
|
||||
cal->set(static_cast<UCalendarDateFields>(i), INT32_MIN);
|
||||
cal->set(static_cast<UCalendarDateFields>(j), INT32_MIN);
|
||||
cal->getTime(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalendarTest::TestChineseCalendarComputeMonthStart() { // ICU-22639
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
|
@ -5740,7 +5791,7 @@ void CalendarTest::TestChineseCalendarComputeMonthStart() { // ICU-22639
|
|||
chinese.hasLeapMonthBetweenWinterSolstices);
|
||||
|
||||
assertEquals("monthStart", monthStart,
|
||||
chinese.handleComputeMonthStart(eyear, 0, false));
|
||||
chinese.handleComputeMonthStart(eyear, 0, false, status));
|
||||
|
||||
// Calling a const method must not haved changed the state of the object.
|
||||
assertFalse("hasLeapMonthBetweenWinterSolstices [#2]",
|
||||
|
|
|
@ -340,6 +340,7 @@ public: // package
|
|||
void Test22633PersianOverflow();
|
||||
void Test22633HebrewOverflow();
|
||||
void Test22633AMPMOverflow();
|
||||
void Test22633SetGetTimeOverflow();
|
||||
|
||||
void verifyFirstDayOfWeek(const char* locale, UCalendarDaysOfWeek expected);
|
||||
void TestFirstDayOfWeek();
|
||||
|
|
Loading…
Add table
Reference in a new issue