From 4d6f08ddac5337a93892284708484293b96df15c Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Tue, 7 Jan 2025 14:45:35 -0800 Subject: [PATCH] ICU-22991 Clean up calendar --- icu4c/source/i18n/basictz.cpp | 12 +++--- icu4c/source/i18n/calendar.cpp | 14 ++----- icu4c/source/i18n/chnsecal.cpp | 8 +--- icu4c/source/i18n/erarules.cpp | 5 ++- icu4c/source/i18n/gregoimp.cpp | 69 ++++++++++++++++++++++++++---- icu4c/source/i18n/gregoimp.h | 74 +++++++++++++++++++++++++++------ icu4c/source/i18n/indiancal.cpp | 17 +------- icu4c/source/i18n/olsontz.cpp | 3 +- icu4c/source/i18n/simpletz.cpp | 3 +- icu4c/source/i18n/timezone.cpp | 3 +- icu4c/source/i18n/tzrule.cpp | 6 +-- icu4c/source/i18n/vtzone.cpp | 21 +++++----- 12 files changed, 157 insertions(+), 78 deletions(-) diff --git a/icu4c/source/i18n/basictz.cpp b/icu4c/source/i18n/basictz.cpp index a2c1ec7fb914..610a31ad5dc5 100644 --- a/icu4c/source/i18n/basictz.cpp +++ b/icu4c/source/i18n/basictz.cpp @@ -160,12 +160,13 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) && (date + MILLIS_PER_YEAR > nextTransitionTime)) { - int32_t year, month, dom, dow, doy, mid; + int32_t year, mid; + int8_t month, dom, dow; UDate d; // Get local wall time for the next transition time Grego::timeToFields(nextTransitionTime + initialRaw + initialDst, - year, month, dom, dow, doy, mid, status); + year, month, dom, dow, mid, status); if (U_FAILURE(status)) return; int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); // Create DOW rule @@ -193,7 +194,7 @@ 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, status); + year, month, dom, dow, mid, status); if (U_FAILURE(status)) return; weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); // Generate another DOW rule @@ -225,7 +226,7 @@ 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, status); + year, month, dom, dow, mid, status); if (U_FAILURE(status)) return; weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); @@ -486,8 +487,7 @@ 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, status); + int32_t year = Grego::timeToYear(tzt.getTime(), status); if (U_FAILURE(status)) { return; } diff --git a/icu4c/source/i18n/calendar.cpp b/icu4c/source/i18n/calendar.cpp index 4c3884871582..167d8644827a 100644 --- a/icu4c/source/i18n/calendar.cpp +++ b/icu4c/source/i18n/calendar.cpp @@ -1524,22 +1524,14 @@ void Calendar::computeGregorianFields(int32_t julianDay, UErrorCode& ec) { if (U_FAILURE(ec)) { return; } - int32_t gregorianDayOfWeekUnused; if (uprv_add32_overflow( julianDay, -kEpochStartAsJulianDay, &julianDay)) { ec = U_ILLEGAL_ARGUMENT_ERROR; return; } - int32_t gregorianMonth, gregorianDayOfMonth, gregorianDayOfYear; - Grego::dayToFields(julianDay, fGregorianYear, gregorianMonth, - gregorianDayOfMonth, gregorianDayOfWeekUnused, - gregorianDayOfYear, ec); - U_ASSERT(gregorianMonth <= 12); - U_ASSERT(gregorianDayOfMonth <= 31); - U_ASSERT(gregorianDayOfYear <= 366); - fGregorianMonth = gregorianMonth; - fGregorianDayOfMonth = gregorianDayOfMonth; - fGregorianDayOfYear = gregorianDayOfYear; + Grego::dayToFields(julianDay, fGregorianYear, fGregorianMonth, + fGregorianDayOfMonth, + fGregorianDayOfYear, ec); } /** diff --git a/icu4c/source/i18n/chnsecal.cpp b/icu4c/source/i18n/chnsecal.cpp index 70b37f19073c..8257bbafb677 100644 --- a/icu4c/source/i18n/chnsecal.cpp +++ b/icu4c/source/i18n/chnsecal.cpp @@ -369,13 +369,9 @@ int64_t ChineseCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, U isLeapMonth = internalGet(UCAL_IS_LEAP_MONTH) != 0; } - int32_t unusedMonth; - int32_t unusedDayOfWeek; - int32_t unusedDayOfMonth; - int32_t unusedDayOfYear; - Grego::dayToFields(newMoon, gyear, unusedMonth, unusedDayOfWeek, unusedDayOfMonth, unusedDayOfYear, status); + int32_t newMonthYear = Grego::dayToYear(newMoon, status); - struct MonthInfo monthInfo = computeMonthInfo(setting, gyear, newMoon, status); + struct MonthInfo monthInfo = computeMonthInfo(setting, newMonthYear, newMoon, status); if (U_FAILURE(status)) { return 0; } diff --git a/icu4c/source/i18n/erarules.cpp b/icu4c/source/i18n/erarules.cpp index 8ab6f00ae04b..d23d7d516c72 100644 --- a/icu4c/source/i18n/erarules.cpp +++ b/icu4c/source/i18n/erarules.cpp @@ -305,8 +305,9 @@ void EraRules::initCurrentEra() { localMillis += (rawOffset + dstOffset); } - int year, month0, dom, dow, doy, mid; - Grego::timeToFields(localMillis, year, month0, dom, dow, doy, mid, ec); + int32_t year, mid; + int8_t month0, dom; + Grego::timeToFields(localMillis, year, month0, dom, mid, ec); if (U_FAILURE(ec)) return; int currentEncodedDate = encodeDate(year, month0 + 1 /* changes to 1-base */, dom); int eraIdx = numEras - 1; diff --git a/icu4c/source/i18n/gregoimp.cpp b/icu4c/source/i18n/gregoimp.cpp index d5c8437a9b80..ef9996a9089f 100644 --- a/icu4c/source/i18n/gregoimp.cpp +++ b/icu4c/source/i18n/gregoimp.cpp @@ -117,8 +117,8 @@ int64_t Grego::fieldsToDay(int32_t year, int32_t month, int32_t dom) { return julian - JULIAN_1970_CE; // JD => epoch day } -void Grego::dayToFields(int32_t day, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, int32_t& doy, UErrorCode& status) { +void Grego::dayToFields(int32_t day, int32_t& year, int8_t& month, + int8_t& dom, int8_t& dow, int16_t& doy, UErrorCode& status) { if (U_FAILURE(status)) return; // Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar) @@ -131,14 +131,16 @@ void Grego::dayToFields(int32_t day, int32_t& year, int32_t& month, // representation. We use 400-year, 100-year, and 4-year cycles. // For example, the 4-year cycle has 4 years + 1 leap day; giving // 1461 == 365*4 + 1 days. - int32_t n400 = ClockMath::floorDivide(day, 146097, &doy); // 400-year cycle length - int32_t n100 = ClockMath::floorDivide(doy, 36524, &doy); // 100-year cycle length - int32_t n4 = ClockMath::floorDivide(doy, 1461, &doy); // 4-year cycle length - int32_t n1 = ClockMath::floorDivide(doy, 365, &doy); + int32_t doy32; + int32_t n400 = ClockMath::floorDivide(day, 146097, &doy32); // 400-year cycle length + int32_t n100 = ClockMath::floorDivide(doy32, 36524, &doy32); // 100-year cycle length + int32_t n4 = ClockMath::floorDivide(doy32, 1461, &doy32); // 4-year cycle length + int32_t n1 = ClockMath::floorDivide(doy32, 365, &doy32); year = 400*n400 + 100*n100 + 4*n4 + n1; if (n100 == 4 || n1 == 4) { doy = 365; // Dec 31 at end of 4- or 400-year cycle } else { + doy = doy32; ++year; } @@ -159,8 +161,52 @@ void Grego::dayToFields(int32_t day, int32_t& year, int32_t& month, doy++; // one-based doy } -void Grego::timeToFields(UDate time, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid, UErrorCode& status) { +int32_t Grego::dayToYear(int32_t day, UErrorCode& status) { + if (U_FAILURE(status)) return 0; + // Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar) + if (uprv_add32_overflow(day, JULIAN_1970_CE - JULIAN_1_CE, &day)) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + // Convert from the day number to the multiple radix + // representation. We use 400-year, 100-year, and 4-year cycles. + // For example, the 4-year cycle has 4 years + 1 leap day; giving + // 1461 == 365*4 + 1 days. + int32_t doy; + int32_t n400 = ClockMath::floorDivide(day, 146097, &doy); // 400-year cycle length + int32_t n100 = ClockMath::floorDivide(doy, 36524, &doy); // 100-year cycle length + int32_t n4 = ClockMath::floorDivide(doy, 1461, &doy); // 4-year cycle length + int32_t n1 = ClockMath::floorDivide(doy, 365, &doy); + int32_t year = 400*n400 + 100*n100 + 4*n4 + n1; + if (!(n100 == 4 || n1 == 4)) { + ++year; + } + return year; +} +void Grego::dayToFields(int32_t day, int32_t& year, int8_t& month, + int8_t& dom, int8_t& dow, UErrorCode& status) { + int16_t unusedDOY; + dayToFields(day, year, month, dom, dow, unusedDOY, status); +} +void Grego::dayToFields(int32_t day, int32_t& year, int8_t& month, + int8_t& dom, int16_t& doy, UErrorCode& status) { + int8_t unusedDOW; + dayToFields(day, year, month, dom, unusedDOW, doy, status); +} + +void Grego::timeToFields(UDate time, int32_t& year, int8_t& month, + int8_t& dom, int32_t& mid, UErrorCode& status) { + int8_t unusedDOW; + timeToFields(time, year, month, dom, unusedDOW, mid, status); +} +void Grego::timeToFields(UDate time, int32_t& year, int8_t& month, + int8_t& dom, int8_t& dow, int32_t& mid, UErrorCode& status) { + int16_t unusedDOY; + timeToFields(time, year, month, dom, dow, unusedDOY, mid, status); +} +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); @@ -168,6 +214,13 @@ void Grego::timeToFields(UDate time, int32_t& year, int32_t& month, dayToFields(day, year, month, dom, dow, doy, status); } +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); + return Grego::dayToYear(day, status); +} + int32_t Grego::dayOfWeek(int32_t day) { int32_t dow; ClockMath::floorDivide(day + int{UCAL_THURSDAY}, 7, &dow); diff --git a/icu4c/source/i18n/gregoimp.h b/icu4c/source/i18n/gregoimp.h index e069fb60de79..b3b868072b3f 100644 --- a/icu4c/source/i18n/gregoimp.h +++ b/icu4c/source/i18n/gregoimp.h @@ -210,8 +210,21 @@ class Grego { * @param doy output parameter to receive day-of-year (1-based) * @param status error code. */ - static void dayToFields(int32_t day, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, int32_t& doy, UErrorCode& status); + static void dayToFields(int32_t day, int32_t& year, int8_t& month, + int8_t& dom, int8_t& dow, int16_t& doy, UErrorCode& status); + + /** + * Convert a 1970-epoch day number to proleptic Gregorian year, + * month, day-of-month, and day-of-week. + * @param day 1970-epoch day + * @param year output parameter to receive year + * @param month output parameter to receive month (0-based, 0==Jan) + * @param dom output parameter to receive day-of-month (1-based) + * @param doy output parameter to receive day-of-year (1-based) + * @param status error code. + */ + static void dayToFields(int32_t day, int32_t& year, int8_t& month, + int8_t& dom, int16_t& doy, UErrorCode& status); /** * Convert a 1970-epoch day number to proleptic Gregorian year, @@ -223,8 +236,16 @@ class Grego { * @param dow output parameter to receive day-of-week (1-based, 1==Sun) * @param status error code. */ - static inline void dayToFields(int32_t day, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, UErrorCode& status); + static void dayToFields(int32_t day, int32_t& year, int8_t& month, + int8_t& dom, int8_t& dow, UErrorCode& status); + + /** + * Convert a 1970-epoch day number to proleptic Gregorian year. + * @param day 1970-epoch day + * @param status error code. + * @return year. + */ + static int32_t dayToYear(int32_t day, UErrorCode& status); /** * Convert a 1970-epoch milliseconds to proleptic Gregorian year, @@ -238,8 +259,43 @@ class Grego { * @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, UErrorCode& status); + static void timeToFields(UDate time, int32_t& year, int8_t& month, + int8_t& dom, int8_t& dow, int16_t& doy, int32_t& mid, UErrorCode& status); + + /** + * Convert a 1970-epoch milliseconds to proleptic Gregorian year, + * month, day-of-month, and day-of-week, day of year and millis-in-day. + * @param time 1970-epoch milliseconds + * @param year output parameter to receive year + * @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 mid output parameter to receive millis-in-day + * @param status error code. + */ + static void timeToFields(UDate time, int32_t& year, int8_t& month, + int8_t& dom, int8_t& dow, int32_t& mid, UErrorCode& status); + + /** + * Convert a 1970-epoch milliseconds to proleptic Gregorian year, + * month, day-of-month, and day-of-week, day of year and millis-in-day. + * @param time 1970-epoch milliseconds + * @param year output parameter to receive year + * @param month output parameter to receive month (0-based, 0==Jan) + * @param dom output parameter to receive day-of-month (1-based) + * @param mid output parameter to receive millis-in-day + * @param status error code. + */ + static void timeToFields(UDate time, int32_t& year, int8_t& month, + int8_t& dom, int32_t& mid, UErrorCode& status); + + /** + * Convert a 1970-epoch milliseconds to proleptic Gregorian year. + * @param time 1970-epoch milliseconds + * @param status error code. + * @return year. + */ + static int32_t timeToYear(UDate time, UErrorCode& status); /** * Return the day of week on the 1970-epoch day @@ -305,12 +361,6 @@ Grego::previousMonthLength(int y, int m) { return (m > 0) ? monthLength(y, m-1) : 31; } -inline void Grego::dayToFields(int32_t day, int32_t& year, int32_t& month, - int32_t& dom, int32_t& dow, UErrorCode& status) { - int32_t doy_unused; - dayToFields(day,year,month,dom,dow,doy_unused, status); -} - inline double Grego::julianDayToMillis(int32_t julian) { return (static_cast(julian) - kEpochStartAsJulianDay) * kOneDay; diff --git a/icu4c/source/i18n/indiancal.cpp b/icu4c/source/i18n/indiancal.cpp index ca839da4d553..c10702351c9f 100644 --- a/icu4c/source/i18n/indiancal.cpp +++ b/icu4c/source/i18n/indiancal.cpp @@ -142,18 +142,6 @@ static double gregorianToJD(int32_t year, int32_t month, int32_t date) { return Grego::fieldsToDay(year, month, date) + kEpochStartAsJulianDay - 0.5; } -/* - * Returns the Gregorian Date corresponding to a given Julian Day - * Month is 0 based. - * @param jd The Julian Day - */ -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, status); - return gregorianDate; -} - //------------------------------------------------------------------------- // Functions for converting from field values to milliseconds.... @@ -265,10 +253,9 @@ int32_t IndianCalendar::handleGetExtendedYear(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]; + // Stores gregorian date corresponding to Julian day; + int32_t gregorianYear = Grego::dayToYear(julianDay - kEpochStartAsJulianDay, status); - 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 diff --git a/icu4c/source/i18n/olsontz.cpp b/icu4c/source/i18n/olsontz.cpp index 9d9770dd4224..c795e9a38fee 100644 --- a/icu4c/source/i18n/olsontz.cpp +++ b/icu4c/source/i18n/olsontz.cpp @@ -568,9 +568,8 @@ UBool OlsonTimeZone::useDaylightTime() const { return finalZone->useDaylightTime(); } - int32_t year, month, dom, dow, doy, mid; UErrorCode status = U_ZERO_ERROR; - Grego::timeToFields(current, year, month, dom, dow, doy, mid, status); + int32_t year = Grego::timeToYear(current, status); U_ASSERT(U_SUCCESS(status)); if (U_FAILURE(status)) return false; // If error, just return false. diff --git a/icu4c/source/i18n/simpletz.cpp b/icu4c/source/i18n/simpletz.cpp index cbefc29830ff..ec80db440938 100644 --- a/icu4c/source/i18n/simpletz.cpp +++ b/icu4c/source/i18n/simpletz.cpp @@ -518,7 +518,8 @@ SimpleTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingT } rawOffsetGMT = getRawOffset(); - int32_t year, month, dom, dow, millis; + 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; diff --git a/icu4c/source/i18n/timezone.cpp b/icu4c/source/i18n/timezone.cpp index 118dfe2f2af6..e2cf35992f4a 100644 --- a/icu4c/source/i18n/timezone.cpp +++ b/icu4c/source/i18n/timezone.cpp @@ -730,7 +730,8 @@ void TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, // (with 7 args) twice when local == true and DST is // detected in the initial call. for (int32_t pass=0; ; ++pass) { - int32_t year, month, dom, dow, millis; + int32_t year, millis; + int8_t month, dom, dow; double day = ClockMath::floorDivide(date, U_MILLIS_PER_DAY, &millis); // out of the range diff --git a/icu4c/source/i18n/tzrule.cpp b/icu4c/source/i18n/tzrule.cpp index 7507068c8807..8d6a37a844cb 100644 --- a/icu4c/source/i18n/tzrule.cpp +++ b/icu4c/source/i18n/tzrule.cpp @@ -355,9 +355,8 @@ AnnualTimeZoneRule::getNextStart(UDate base, int32_t prevDSTSavings, UBool inclusive, UDate& result) const { - int32_t year, month, dom, dow, doy, mid; UErrorCode status = U_ZERO_ERROR; - Grego::timeToFields(base, year, month, dom, dow, doy, mid, status); + int32_t year = Grego::timeToYear(base, status); U_ASSERT(U_SUCCESS(status)); if (year < fStartYear) { return getFirstStart(prevRawOffset, prevDSTSavings, result); @@ -381,9 +380,8 @@ AnnualTimeZoneRule::getPreviousStart(UDate base, int32_t prevDSTSavings, UBool inclusive, UDate& result) const { - int32_t year, month, dom, dow, doy, mid; UErrorCode status = U_ZERO_ERROR; - Grego::timeToFields(base, year, month, dom, dow, doy, mid, status); + int32_t year = Grego::timeToYear(base, status); U_ASSERT(U_SUCCESS(status)); if (year > fEndYear) { return getFinalStart(prevRawOffset, prevDSTSavings, result); diff --git a/icu4c/source/i18n/vtzone.cpp b/icu4c/source/i18n/vtzone.cpp index 6067c5490e8d..8c0295bdcbe8 100644 --- a/icu4c/source/i18n/vtzone.cpp +++ b/icu4c/source/i18n/vtzone.cpp @@ -182,8 +182,9 @@ static UnicodeString& appendMillis(UDate date, 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, status); + int32_t year, mid; + int8_t month, dom, dow; + Grego::timeToFields(time, year, month, dom, dow, mid, status); if (U_FAILURE(status)) {return str;} str.remove(); @@ -675,9 +676,10 @@ static TimeZoneRule* createRuleByRRULE(const UnicodeString& zonename, int rawOff } // Calculate start/end year and missing fields - int32_t startYear, startMonth, startDOM, startDOW, startDOY, startMID; + int32_t startYear, startMID; + int8_t startMonth, startDOM; Grego::timeToFields(start + fromOffset, startYear, startMonth, startDOM, - startDOW, startDOY, startMID, status); + startMID, status); if (U_FAILURE(status)) { return nullptr; } @@ -692,8 +694,7 @@ 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, status); + endYear = Grego::timeToYear(until, status); if (U_FAILURE(status)) return nullptr; } else { endYear = AnnualTimeZoneRule::MAX_YEAR; @@ -1674,8 +1675,7 @@ VTimeZone::parse(UErrorCode& status) { status); } else { // Update the end year - int32_t y, m, d, dow, doy, mid; - Grego::timeToFields(start, y, m, d, dow, doy, mid, status); + int32_t y = Grego::timeToYear(start, status); if (U_FAILURE(status)) return; newRule.adoptInsteadAndCheckErrorCode( new AnnualTimeZoneRule( @@ -1902,7 +1902,8 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz, int32_t stdCount = 0; AnnualTimeZoneRule *finalStdRule = nullptr; - int32_t year, month, dom, dow, doy, mid; + int32_t year, mid; + int8_t month, dom, dow; UBool hasTransitions = false; TimeZoneTransition tzt; UBool tztAvail; @@ -1922,7 +1923,7 @@ 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, status); + Grego::timeToFields(tzt.getTime() + fromOffset, year, month, dom, dow, mid, status); if (U_FAILURE(status)) return; int32_t weekInMonth = Grego::dayOfWeekInMonth(year, month, dom); UBool sameRule = false;