diff --git a/source/i18n/basictz.cpp b/source/i18n/basictz.cpp index 2490fadc..ce70482b 100644 --- a/source/i18n/basictz.cpp +++ b/source/i18n/basictz.cpp @@ -165,7 +165,8 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, // Get local wall time for the next transition time Grego::timeToFields(nextTransitionTime + initialRaw + initialDst, - year, month, dom, dow, doy, mid); + year, month, dom, dow, doy, mid, status); + if (U_FAILURE(status)) return; int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); // Create DOW rule DateTimeRule *dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); @@ -192,7 +193,8 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, // Get local wall time for the next transition time Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(), - year, month, dom, dow, doy, mid); + year, month, dom, dow, doy, mid, status); + if (U_FAILURE(status)) return; weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); // Generate another DOW rule dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); @@ -223,7 +225,8 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, // Generate another DOW rule Grego::timeToFields(tr.getTime() + tr.getFrom()->getRawOffset() + tr.getFrom()->getDSTSavings(), - year, month, dom, dow, doy, mid); + year, month, dom, dow, doy, mid, status); + if (U_FAILURE(status)) return; weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); tr.getTo()->getName(name); @@ -484,7 +487,10 @@ BasicTimeZone::getTimeZoneRulesAfter(UDate start, InitialTimeZoneRule*& initial, } else { // Calculate the transition year int32_t year, month, dom, dow, doy, mid; - Grego::timeToFields(tzt.getTime(), year, month, dom, dow, doy, mid); + Grego::timeToFields(tzt.getTime(), year, month, dom, dow, doy, mid, status); + if (U_FAILURE(status)) { + return; + } // Re-create the rule ar->getName(name); LocalPointer newAr(new AnnualTimeZoneRule(name, ar->getRawOffset(), ar->getDSTSavings(), diff --git a/source/i18n/calendar.cpp b/source/i18n/calendar.cpp index 4b6edc87..9342b7a8 100644 --- a/source/i18n/calendar.cpp +++ b/source/i18n/calendar.cpp @@ -1580,7 +1580,7 @@ void Calendar::computeGregorianFields(int32_t julianDay, UErrorCode& ec) { return; } int32_t gregorianDayOfWeekUnused; - Grego::dayToFields(julianDay - kEpochStartAsJulianDay, fGregorianYear, fGregorianMonth, fGregorianDayOfMonth, gregorianDayOfWeekUnused, fGregorianDayOfYear); + Grego::dayToFields(julianDay - kEpochStartAsJulianDay, fGregorianYear, fGregorianMonth, fGregorianDayOfMonth, gregorianDayOfWeekUnused, fGregorianDayOfYear, ec); } /** diff --git a/source/i18n/erarules.cpp b/source/i18n/erarules.cpp index 65405bb8..ff270ea6 100644 --- a/source/i18n/erarules.cpp +++ b/source/i18n/erarules.cpp @@ -306,7 +306,8 @@ void EraRules::initCurrentEra() { } int year, month0, dom, dow, doy, mid; - Grego::timeToFields(localMillis, year, month0, dom, dow, doy, mid); + Grego::timeToFields(localMillis, year, month0, dom, dow, doy, mid, ec); + if (U_FAILURE(ec)) return; int currentEncodedDate = encodeDate(year, month0 + 1 /* changes to 1-base */, dom); int eraIdx = numEras - 1; while (eraIdx > 0) { diff --git a/source/i18n/gregoimp.cpp b/source/i18n/gregoimp.cpp index 31b5aeed..b695e4c2 100644 --- a/source/i18n/gregoimp.cpp +++ b/source/i18n/gregoimp.cpp @@ -107,8 +107,8 @@ double Grego::fieldsToDay(int32_t year, int32_t month, int32_t dom) { } void Grego::dayToFields(double day, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, int32_t& doy) { - + int32_t& dom, int32_t& dow, int32_t& doy, UErrorCode& status) { + if (U_FAILURE(status)) return; // Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar) day += JULIAN_1970_CE - JULIAN_1_CE; @@ -145,11 +145,12 @@ void Grego::dayToFields(double day, int32_t& year, int32_t& month, } void Grego::timeToFields(UDate time, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid) { + int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid, UErrorCode& status) { + if (U_FAILURE(status)) return; double millisInDay; double day = ClockMath::floorDivide((double)time, (double)U_MILLIS_PER_DAY, &millisInDay); mid = (int32_t)millisInDay; - dayToFields(day, year, month, dom, dow, doy); + dayToFields(day, year, month, dom, dow, doy, status); } int32_t Grego::dayOfWeek(double day) { diff --git a/source/i18n/gregoimp.h b/source/i18n/gregoimp.h index d65d6a4f..640e2863 100644 --- a/source/i18n/gregoimp.h +++ b/source/i18n/gregoimp.h @@ -189,9 +189,10 @@ class Grego { * @param dom output parameter to receive day-of-month (1-based) * @param dow output parameter to receive day-of-week (1-based, 1==Sun) * @param doy output parameter to receive day-of-year (1-based) + * @param status error code. */ static void dayToFields(double day, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, int32_t& doy); + int32_t& dom, int32_t& dow, int32_t& doy, UErrorCode& status); /** * Convert a 1970-epoch day number to proleptic Gregorian year, @@ -201,9 +202,10 @@ class Grego { * @param month output parameter to receive month (0-based, 0==Jan) * @param dom output parameter to receive day-of-month (1-based) * @param dow output parameter to receive day-of-week (1-based, 1==Sun) + * @param status error code. */ static inline void dayToFields(double day, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow); + int32_t& dom, int32_t& dow, UErrorCode& status); /** * Convert a 1970-epoch milliseconds to proleptic Gregorian year, @@ -215,9 +217,10 @@ class Grego { * @param dow output parameter to receive day-of-week (1-based, 1==Sun) * @param doy output parameter to receive day-of-year (1-based) * @param mid output parameter to receive millis-in-day + * @param status error code. */ static void timeToFields(UDate time, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid); + int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid, UErrorCode& status); /** * Return the day of week on the 1970-epoch day @@ -284,9 +287,9 @@ Grego::previousMonthLength(int y, int m) { } inline void Grego::dayToFields(double day, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow) { + int32_t& dom, int32_t& dow, UErrorCode& status) { int32_t doy_unused; - dayToFields(day,year,month,dom,dow,doy_unused); + dayToFields(day,year,month,dom,dow,doy_unused, status); } inline double Grego::julianDayToMillis(int32_t julian) diff --git a/source/i18n/indiancal.cpp b/source/i18n/indiancal.cpp index 29c2749f..91e32d34 100644 --- a/source/i18n/indiancal.cpp +++ b/source/i18n/indiancal.cpp @@ -148,10 +148,10 @@ static double gregorianToJD(int32_t year, int32_t month, int32_t date) { * Month is 0 based. * @param jd The Julian Day */ -static int32_t* jdToGregorian(double jd, int32_t gregorianDate[3]) { +static int32_t* jdToGregorian(double jd, int32_t gregorianDate[3], UErrorCode& status) { int32_t gdow; Grego::dayToFields(jd - kEpochStartAsJulianDay, - gregorianDate[0], gregorianDate[1], gregorianDate[2], gdow); + gregorianDate[0], gregorianDate[1], gregorianDate[2], gdow, status); return gregorianDate; } @@ -254,13 +254,14 @@ int32_t IndianCalendar::handleGetExtendedYear() { * method is called. The getGregorianXxx() methods return Gregorian * calendar equivalents for the given Julian day. */ -void IndianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& /* status */) { +void IndianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) { double jdAtStartOfGregYear; int32_t leapMonth, IndianYear, yday, IndianMonth, IndianDayOfMonth, mday; int32_t gregorianYear; // Stores gregorian date corresponding to Julian day; int32_t gd[3]; - gregorianYear = jdToGregorian(julianDay, gd)[0]; // Gregorian date for Julian day + gregorianYear = jdToGregorian(julianDay, gd, status)[0]; // Gregorian date for Julian day + if (U_FAILURE(status)) return; IndianYear = gregorianYear - INDIAN_ERA_START; // Year in Saka era jdAtStartOfGregYear = gregorianToJD(gregorianYear, 0, 1); // JD at start of Gregorian year yday = (int32_t)(julianDay - jdAtStartOfGregYear); // Day number in Gregorian year (starting from 0) diff --git a/source/i18n/olsontz.cpp b/source/i18n/olsontz.cpp index 260e345d..e25ab6ef 100644 --- a/source/i18n/olsontz.cpp +++ b/source/i18n/olsontz.cpp @@ -569,7 +569,10 @@ UBool OlsonTimeZone::useDaylightTime() const { } int32_t year, month, dom, dow, doy, mid; - Grego::timeToFields(current, year, month, dom, dow, doy, mid); + UErrorCode status = U_ZERO_ERROR; + Grego::timeToFields(current, year, month, dom, dow, doy, mid, status); + U_ASSERT(U_SUCCESS(status)); + if (U_FAILURE(status)) return false; // If error, just return false. // Find start of this year, and start of next year double start = Grego::fieldsToDay(year, 0, 1) * SECONDS_PER_DAY; diff --git a/source/i18n/simpletz.cpp b/source/i18n/simpletz.cpp index 8b21152f..1b6c0aaf 100644 --- a/source/i18n/simpletz.cpp +++ b/source/i18n/simpletz.cpp @@ -521,7 +521,8 @@ SimpleTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingT int32_t year, month, dom, dow, millis; int32_t day = ClockMath::floorDivide(date, U_MILLIS_PER_DAY, &millis); - Grego::dayToFields(day, year, month, dom, dow); + Grego::dayToFields(day, year, month, dom, dow, status); + if (U_FAILURE(status)) return; savingsDST = getOffset(GregorianCalendar::AD, year, month, dom, (uint8_t) dow, millis, @@ -549,7 +550,8 @@ SimpleTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingT } if (recalc) { day = ClockMath::floorDivide(date, U_MILLIS_PER_DAY, &millis); - Grego::dayToFields(day, year, month, dom, dow); + Grego::dayToFields(day, year, month, dom, dow, status); + if (U_FAILURE(status)) return; savingsDST = getOffset(GregorianCalendar::AD, year, month, dom, (uint8_t) dow, millis, Grego::monthLength(year, month), diff --git a/source/i18n/timezone.cpp b/source/i18n/timezone.cpp index 02cbc78c..72ccf22b 100644 --- a/source/i18n/timezone.cpp +++ b/source/i18n/timezone.cpp @@ -732,7 +732,8 @@ void TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, int32_t year, month, dom, dow, millis; double day = ClockMath::floorDivide(date, U_MILLIS_PER_DAY, &millis); - Grego::dayToFields(day, year, month, dom, dow); + Grego::dayToFields(day, year, month, dom, dow, ec); + if (U_FAILURE(ec)) return; dstOffset = getOffset(GregorianCalendar::AD, year, month, dom, (uint8_t) dow, millis, diff --git a/source/i18n/tzrule.cpp b/source/i18n/tzrule.cpp index a3522f1d..2ec57c9c 100644 --- a/source/i18n/tzrule.cpp +++ b/source/i18n/tzrule.cpp @@ -356,7 +356,9 @@ AnnualTimeZoneRule::getNextStart(UDate base, UBool inclusive, UDate& result) const { int32_t year, month, dom, dow, doy, mid; - Grego::timeToFields(base, year, month, dom, dow, doy, mid); + UErrorCode status = U_ZERO_ERROR; + Grego::timeToFields(base, year, month, dom, dow, doy, mid, status); + U_ASSERT(U_SUCCESS(status)); if (year < fStartYear) { return getFirstStart(prevRawOffset, prevDSTSavings, result); } @@ -380,7 +382,9 @@ AnnualTimeZoneRule::getPreviousStart(UDate base, UBool inclusive, UDate& result) const { int32_t year, month, dom, dow, doy, mid; - Grego::timeToFields(base, year, month, dom, dow, doy, mid); + UErrorCode status = U_ZERO_ERROR; + Grego::timeToFields(base, year, month, dom, dow, doy, mid, status); + U_ASSERT(U_SUCCESS(status)); if (year > fEndYear) { return getFinalStart(prevRawOffset, prevDSTSavings, result); } diff --git a/source/i18n/vtzone.cpp b/source/i18n/vtzone.cpp index 25af556a..c5168b19 100644 --- a/source/i18n/vtzone.cpp +++ b/source/i18n/vtzone.cpp @@ -180,9 +180,11 @@ static UnicodeString& appendMillis(UDate date, UnicodeString& str) { /* * Convert date/time to RFC2445 Date-Time form #1 DATE WITH LOCAL TIME */ -static UnicodeString& getDateTimeString(UDate time, UnicodeString& str) { +static UnicodeString& getDateTimeString(UDate time, UnicodeString& str, UErrorCode& status) { + if (U_FAILURE(status)) {return str;} int32_t year, month, dom, dow, doy, mid; - Grego::timeToFields(time, year, month, dom, dow, doy, mid); + Grego::timeToFields(time, year, month, dom, dow, doy, mid, status); + if (U_FAILURE(status)) {return str;} str.remove(); appendAsciiDigits(year, 4, str); @@ -206,8 +208,8 @@ static UnicodeString& getDateTimeString(UDate time, UnicodeString& str) { /* * Convert date/time to RFC2445 Date-Time form #2 DATE WITH UTC TIME */ -static UnicodeString& getUTCDateTimeString(UDate time, UnicodeString& str) { - getDateTimeString(time, str); +static UnicodeString& getUTCDateTimeString(UDate time, UnicodeString& str, UErrorCode& status) { + getDateTimeString(time, str, status); str.append((char16_t)0x005A /*'Z'*/); return str; } @@ -675,7 +677,10 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff // Calculate start/end year and missing fields int32_t startYear, startMonth, startDOM, startDOW, startDOY, startMID; Grego::timeToFields(start + fromOffset, startYear, startMonth, startDOM, - startDOW, startDOY, startMID); + startDOW, startDOY, startMID, status); + if (U_FAILURE(status)) { + return nullptr; + } if (month == -1) { // If BYMONTH is not set, use the month of DTSTART month = startMonth; @@ -688,7 +693,8 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff int32_t endYear; if (until != MIN_MILLIS) { int32_t endMonth, endDOM, endDOW, endDOY, endMID; - Grego::timeToFields(until, endYear, endMonth, endDOM, endDOW, endDOY, endMID); + Grego::timeToFields(until, endYear, endMonth, endDOM, endDOW, endDOY, endMID, status); + if (U_FAILURE(status)) return nullptr; } else { endYear = AnnualTimeZoneRule::MAX_YEAR; } @@ -1673,7 +1679,8 @@ VTimeZone::parse(UErrorCode& status) { } else { // Update the end year int32_t y, m, d, dow, doy, mid; - Grego::timeToFields(start, y, m, d, dow, doy, mid); + Grego::timeToFields(start, y, m, d, dow, doy, mid, status); + if (U_FAILURE(status)) return; newRule.adoptInsteadAndCheckErrorCode( new AnnualTimeZoneRule( finalRule->getName(tznam), @@ -1713,6 +1720,7 @@ VTimeZone::parse(UErrorCode& status) { void VTimeZone::write(VTZWriter& writer, UErrorCode& status) const { + if (U_FAILURE(status)) return; if (vtzlines != nullptr) { for (int32_t i = 0; i < vtzlines->size(); i++) { UnicodeString *line = (UnicodeString*)vtzlines->elementAt(i); @@ -1727,7 +1735,8 @@ VTimeZone::write(VTZWriter& writer, UErrorCode& status) const { UnicodeString utcString; writer.write(ICAL_LASTMOD); writer.write(COLON); - writer.write(getUTCDateTimeString(lastmod, utcString)); + writer.write(getUTCDateTimeString(lastmod, utcString, status)); + if (U_FAILURE(status)) return; writer.write(ICAL_NEWLINE); } else { writer.write(*line); @@ -1917,7 +1926,8 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, int32_t fromOffset = tzt.getFrom()->getRawOffset() + tzt.getFrom()->getDSTSavings(); int32_t fromDSTSavings = tzt.getFrom()->getDSTSavings(); int32_t toOffset = tzt.getTo()->getRawOffset() + tzt.getTo()->getDSTSavings(); - Grego::timeToFields(tzt.getTime() + fromOffset, year, month, dom, dow, doy, mid); + Grego::timeToFields(tzt.getTime() + fromOffset, year, month, dom, dow, doy, mid, status); + if (U_FAILURE(status)) return; int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); UBool sameRule = false; const AnnualTimeZoneRule *atzrule; @@ -2166,7 +2176,7 @@ VTimeZone::writeHeaders(VTZWriter& writer, UErrorCode& status) const { UnicodeString lastmodStr; writer.write(ICAL_LASTMOD); writer.write(COLON); - writer.write(getUTCDateTimeString(lastmod, lastmodStr)); + writer.write(getUTCDateTimeString(lastmod, lastmodStr, status)); writer.write(ICAL_NEWLINE); } } @@ -2203,8 +2213,11 @@ VTimeZone::writeZonePropsByTime(VTZWriter& writer, UBool isDst, const UnicodeStr writer.write(ICAL_RDATE); writer.write(COLON); UnicodeString timestr; - writer.write(getDateTimeString(time + fromOffset, timestr)); + writer.write(getDateTimeString(time + fromOffset, timestr, status)); writer.write(ICAL_NEWLINE); + if (U_FAILURE(status)) { + return; + } } endZoneProps(writer, isDst, status); if (U_FAILURE(status)) { @@ -2237,7 +2250,7 @@ VTimeZone::writeZonePropsByDOM(VTZWriter& writer, UBool isDst, const UnicodeStri appendAsciiDigits(dayOfMonth, 0, dstr); writer.write(dstr); if (untilTime != MAX_MILLIS) { - appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr), status); + appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr, status), status); if (U_FAILURE(status)) { return; } @@ -2273,7 +2286,7 @@ VTimeZone::writeZonePropsByDOW(VTZWriter& writer, UBool isDst, const UnicodeStri writer.write(ICAL_DOW_NAMES[dayOfWeek - 1]); // SU, MO, TU... if (untilTime != MAX_MILLIS) { - appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr), status); + appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr, status), status); if (U_FAILURE(status)) { return; } @@ -2398,7 +2411,7 @@ VTimeZone::writeZonePropsByDOW_GEQ_DOM_sub(VTZWriter& writer, int32_t month, int } if (untilTime != MAX_MILLIS) { - appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr), status); + appendUNTIL(writer, getDateTimeString(untilTime + fromOffset, dstr, status), status); if (U_FAILURE(status)) { return; } @@ -2537,7 +2550,10 @@ VTimeZone::beginZoneProps(VTZWriter& writer, UBool isDst, const UnicodeString& z // DTSTART writer.write(ICAL_DTSTART); writer.write(COLON); - writer.write(getDateTimeString(startTime + fromOffset, dstr)); + writer.write(getDateTimeString(startTime + fromOffset, dstr, status)); + if (U_FAILURE(status)) { + return; + } writer.write(ICAL_NEWLINE); }