diff --git a/icu4c/source/i18n/gregoimp.cpp b/icu4c/source/i18n/gregoimp.cpp index 161897b027a2..5a3d22ae9a38 100644 --- a/icu4c/source/i18n/gregoimp.cpp +++ b/icu4c/source/i18n/gregoimp.cpp @@ -86,7 +86,6 @@ double ClockMath::floorDivide(double dividend, double divisor, r = dividend - (quotient * divisor); } } - U_ASSERT(0 <= r && r < divisor); if (remainder != nullptr) { *remainder = r; } @@ -204,7 +203,11 @@ void Grego::timeToFields(UDate time, int32_t& year, int8_t& month, int8_t& dom, int8_t& dow, int16_t& doy, int32_t& mid, UErrorCode& status) { if (U_FAILURE(status)) return; double millisInDay; - double day = ClockMath::floorDivide(static_cast(time), static_cast(U_MILLIS_PER_DAY), &millisInDay); + double day = ClockMath::floorDivide(time, U_MILLIS_PER_DAY, &millisInDay); + if (day > INT32_MAX || day < INT32_MIN) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } mid = static_cast(millisInDay); dayToFields(day, year, month, dom, dow, doy, status); } @@ -212,7 +215,11 @@ void Grego::timeToFields(UDate time, int32_t& year, int8_t& month, int32_t Grego::timeToYear(UDate time, UErrorCode& status) { if (U_FAILURE(status)) return 0; double millisInDay; - int32_t day = ClockMath::floorDivide(static_cast(time), static_cast(U_MILLIS_PER_DAY), &millisInDay); + double day = ClockMath::floorDivide(time, U_MILLIS_PER_DAY, &millisInDay); + if (day > INT32_MAX || day < INT32_MIN) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } return Grego::dayToYear(day, status); } diff --git a/icu4c/source/i18n/simpletz.cpp b/icu4c/source/i18n/simpletz.cpp index ec80db440938..3f3b236ea45c 100644 --- a/icu4c/source/i18n/simpletz.cpp +++ b/icu4c/source/i18n/simpletz.cpp @@ -520,14 +520,8 @@ SimpleTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingT rawOffsetGMT = getRawOffset(); int32_t year, millis; int8_t month, dom, dow; - 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, status); + Grego::timeToFields(date, year, month, dom, dow, millis, status); if (U_FAILURE(status)) return; savingsDST = getOffset(GregorianCalendar::AD, year, month, dom, @@ -555,8 +549,7 @@ SimpleTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingT } } if (recalc) { - day = ClockMath::floorDivide(date, U_MILLIS_PER_DAY, &millis); - Grego::dayToFields(day, year, month, dom, dow, status); + Grego::timeToFields(date, year, month, dom, dow, millis, status); if (U_FAILURE(status)) return; savingsDST = getOffset(GregorianCalendar::AD, year, month, dom, static_cast(dow), millis, diff --git a/icu4c/source/i18n/timezone.cpp b/icu4c/source/i18n/timezone.cpp index e2cf35992f4a..bc3a6420831e 100644 --- a/icu4c/source/i18n/timezone.cpp +++ b/icu4c/source/i18n/timezone.cpp @@ -732,14 +732,7 @@ void TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, for (int32_t pass=0; ; ++pass) { int32_t year, millis; int8_t month, dom, dow; - double day = ClockMath::floorDivide(date, U_MILLIS_PER_DAY, &millis); - - // out of the range - if (day < INT32_MIN || day > INT32_MAX) { - ec = U_ILLEGAL_ARGUMENT_ERROR; - return; - } - Grego::dayToFields(day, year, month, dom, dow, ec); + Grego::timeToFields(date, year, month, dom, dow, millis, ec); if (U_FAILURE(ec)) return; dstOffset = getOffset(GregorianCalendar::AD, year, month, dom,