diff --git a/icu4c/source/i18n/basictz.cpp b/icu4c/source/i18n/basictz.cpp index 12c9e163c5d..f98625a3f05 100644 --- a/icu4c/source/i18n/basictz.cpp +++ b/icu4c/source/i18n/basictz.cpp @@ -547,14 +547,23 @@ error: } void -BasicTimeZone::getOffsetFromLocal(UDate /*date*/, int32_t /*nonExistingTimeOpt*/, int32_t /*duplicatedTimeOpt*/, - int32_t& /*rawOffset*/, int32_t& /*dstOffset*/, UErrorCode& status) const { +BasicTimeZone::getOffsetFromLocal(UDate /*date*/, UTimeZoneLocalOption /*nonExistingTimeOpt*/, + UTimeZoneLocalOption /*duplicatedTimeOpt*/, + int32_t& /*rawOffset*/, int32_t& /*dstOffset*/, + UErrorCode& status) const { if (U_FAILURE(status)) { return; } status = U_UNSUPPORTED_ERROR; } +void BasicTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + int32_t& rawOffset, int32_t& dstOffset, + UErrorCode& status) const { + getOffsetFromLocal(date, (UTimeZoneLocalOption)nonExistingTimeOpt, + (UTimeZoneLocalOption)duplicatedTimeOpt, rawOffset, dstOffset, status); +} + U_NAMESPACE_END #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/olsontz.cpp b/icu4c/source/i18n/olsontz.cpp index aa2ad7fc468..1d0fa804b20 100644 --- a/icu4c/source/i18n/olsontz.cpp +++ b/icu4c/source/i18n/olsontz.cpp @@ -399,9 +399,9 @@ void OlsonTimeZone::getOffset(UDate date, UBool local, int32_t& rawoff, } } -void -OlsonTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, - int32_t& rawoff, int32_t& dstoff, UErrorCode& ec) const { +void OlsonTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, + int32_t& rawoff, int32_t& dstoff, UErrorCode& ec) const { if (U_FAILURE(ec)) { return; } diff --git a/icu4c/source/i18n/olsontz.h b/icu4c/source/i18n/olsontz.h index 275b1b4add3..f1d862fc757 100644 --- a/icu4c/source/i18n/olsontz.h +++ b/icu4c/source/i18n/olsontz.h @@ -187,8 +187,10 @@ class U_I18N_API OlsonTimeZone: public BasicTimeZone { /** * BasicTimeZone API. */ - virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, - int32_t& rawoff, int32_t& dstoff, UErrorCode& ec) const; + virtual void getOffsetFromLocal( + UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, + int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const; /** * TimeZone API. This method has no effect since objects of this diff --git a/icu4c/source/i18n/rbtz.cpp b/icu4c/source/i18n/rbtz.cpp index 3249a32a1cf..ddaa804f2cc 100644 --- a/icu4c/source/i18n/rbtz.cpp +++ b/icu4c/source/i18n/rbtz.cpp @@ -403,9 +403,9 @@ RuleBasedTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, getOffsetInternal(date, local, kFormer, kLatter, rawOffset, dstOffset, status); } -void -RuleBasedTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, - int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const { +void RuleBasedTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, + int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const { getOffsetInternal(date, TRUE, nonExistingTimeOpt, duplicatedTimeOpt, rawOffset, dstOffset, status); } diff --git a/icu4c/source/i18n/simpletz.cpp b/icu4c/source/i18n/simpletz.cpp index 0b1921eee8f..02dafb76f8d 100644 --- a/icu4c/source/i18n/simpletz.cpp +++ b/icu4c/source/i18n/simpletz.cpp @@ -509,8 +509,10 @@ SimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, } void -SimpleTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, - int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) const { +SimpleTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffsetGMT, + int32_t& savingsDST, UErrorCode& status) const +{ if (U_FAILURE(status)) { return; } diff --git a/icu4c/source/i18n/ucal.cpp b/icu4c/source/i18n/ucal.cpp index c30ce093352..099e9e315a7 100644 --- a/icu4c/source/i18n/ucal.cpp +++ b/icu4c/source/i18n/ucal.cpp @@ -828,4 +828,28 @@ ucal_getTimeZoneIDForWindowsID(const UChar* winid, int32_t len, const char* regi return resultLen; } +U_CAPI void U_EXPORT2 ucal_getTimeZoneOffsetFromLocal( + const UCalendar* cal, + UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, + int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status) +{ + if (U_FAILURE(*status)) { + return; + } + UDate date = ((Calendar*)cal)->getTime(*status); + if (U_FAILURE(*status)) { + return; + } + const TimeZone& tz = ((Calendar*)cal)->getTimeZone(); + const BasicTimeZone* btz = dynamic_cast(&tz); + if (btz == nullptr) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + btz->getOffsetFromLocal( + date, nonExistingTimeOpt, duplicatedTimeOpt, + *rawOffset, *dstOffset, *status); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/i18n/unicode/basictz.h b/icu4c/source/i18n/unicode/basictz.h index 7dd981abf93..0c88d4922d4 100644 --- a/icu4c/source/i18n/unicode/basictz.h +++ b/icu4c/source/i18n/unicode/basictz.h @@ -152,6 +152,17 @@ public: virtual void getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, AnnualTimeZoneRule*& std, AnnualTimeZoneRule*& dst, UErrorCode& status) const; +#ifndef U_FORCE_HIDE_DRAFT_API + /** + * Get time zone offsets from local wall time. + * @draft ICU 69 + */ + virtual void getOffsetFromLocal( + UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffset, + int32_t& dstOffset, UErrorCode& status) const; + +#endif /* U_FORCE_HIDE_DRAFT_API */ #ifndef U_HIDE_INTERNAL_API /** @@ -161,8 +172,8 @@ public: enum { kStandard = 0x01, kDaylight = 0x03, - kFormer = 0x04, - kLatter = 0x0C + kFormer = 0x04, /* UCAL_TZ_LOCAL_FORMER */ + kLatter = 0x0C /* UCAL_TZ_LOCAL_LATTER */ }; #endif /* U_HIDE_INTERNAL_API */ @@ -170,7 +181,7 @@ public: * Get time zone offsets from local wall time. * @internal */ - virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const; protected: diff --git a/icu4c/source/i18n/unicode/rbtz.h b/icu4c/source/i18n/unicode/rbtz.h index 06d566aa714..15098141d44 100644 --- a/icu4c/source/i18n/unicode/rbtz.h +++ b/icu4c/source/i18n/unicode/rbtz.h @@ -302,12 +302,16 @@ public: virtual void getTimeZoneRules(const InitialTimeZoneRule*& initial, const TimeZoneRule* trsrules[], int32_t& trscount, UErrorCode& status) const; +#ifndef U_FORCE_HIDE_DRAFT_API /** * Get time zone offsets from local wall time. - * @internal + * @draft ICU 69 */ - virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + virtual void getOffsetFromLocal( + UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const; +#endif /* U_FORCE_HIDE_DRAFT_API */ private: void deleteRules(void); diff --git a/icu4c/source/i18n/unicode/simpletz.h b/icu4c/source/i18n/unicode/simpletz.h index 792fddb4d9d..f85b04072ef 100644 --- a/icu4c/source/i18n/unicode/simpletz.h +++ b/icu4c/source/i18n/unicode/simpletz.h @@ -620,12 +620,16 @@ public: virtual void getOffset(UDate date, UBool local, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& ec) const; +#ifndef U_FORCE_HIDE_DRAFT_API /** * Get time zone offsets from local wall time. - * @internal + * @draft ICU 69 */ - virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + virtual void getOffsetFromLocal( + UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const; +#endif /* U_FORCE_HIDE_DRAFT_API */ /** * Returns the TimeZone's raw GMT offset (i.e., the number of milliseconds to add diff --git a/icu4c/source/i18n/unicode/ucal.h b/icu4c/source/i18n/unicode/ucal.h index 89b16042437..509adb26095 100644 --- a/icu4c/source/i18n/unicode/ucal.h +++ b/icu4c/source/i18n/unicode/ucal.h @@ -1617,6 +1617,102 @@ U_CAPI int32_t U_EXPORT2 ucal_getTimeZoneIDForWindowsID(const UChar* winid, int32_t len, const char* region, UChar* id, int32_t idCapacity, UErrorCode* status); +#ifndef U_FORCE_HIDE_DRAFT_API +/** + * Options used by ucal_getTimeZoneOffsetFromLocal and BasicTimeZone::getOffsetFromLocal() + * to specify how to interpret an input time when it does not exist, or when it is ambiguous, + * around a time zone transition. + * @draft ICU 69 + */ +enum UTimeZoneLocalOption { +#ifndef U_HIDE_DRAFT_API + /** + * An input time is always interpreted as local time before + * a time zone transition. + * @draft ICU 69 + */ + UCAL_TZ_LOCAL_FORMER = 0x04, + /** + * An input time is always interpreted as local time after + * a time zone transition. + * @draft ICU 69 + */ + UCAL_TZ_LOCAL_LATTER = 0x0C, + /** + * An input time is interpreted as standard time when local + * time is switched to/from daylight saving time. When both + * sides of a time zone transition are standard time, + * or daylight saving time, the local time before the + * transition is used. + * @draft ICU 69 + */ + UCAL_TZ_LOCAL_STANDARD_FORMER = UCAL_TZ_LOCAL_FORMER | 0x01, + /** + * An input time is interpreted as standard time when local + * time is switched to/from daylight saving time. When both + * sides of a time zone transition are standard time, + * or daylight saving time, the local time after the + * transition is used. + * @draft ICU 69 + */ + UCAL_TZ_LOCAL_STANDARD_LATTER = UCAL_TZ_LOCAL_LATTER | 0x01, + /** + * An input time is interpreted as daylight saving time when + * local time is switched to/from standard time. When both + * sides of a time zone transition are standard time, + * or daylight saving time, the local time before the + * transition is used. + * @draft ICU 69 + */ + UCAL_TZ_LOCAL_DAYLIGHT_FORMER = UCAL_TZ_LOCAL_FORMER | 0x03, + /** + * An input time is interpreted as daylight saving time when + * local time is switched to/from standard time. When both + * sides of a time zone transition are standard time, + * or daylight saving time, the local time after the + * transition is used. + * @draft ICU 69 + */ + UCAL_TZ_LOCAL_DAYLIGHT_LATTER = UCAL_TZ_LOCAL_LATTER | 0x03, +#endif /* U_HIDE_DRAFT_API */ +}; +typedef enum UTimeZoneLocalOption UTimeZoneLocalOption; /**< @draft ICU 69 */ + +/** +* Returns the time zone raw and GMT offset for the given moment +* in time. Upon return, local-millis = GMT-millis + rawOffset + +* dstOffset. All computations are performed in the proleptic +* Gregorian calendar. +* +* @param cal The UCalendar which specify the local date and time value to query. +* @param nonExistingTimeOpt The option to indicate how to interpret the date and +* time in the calendar represent a local time that skipped at a positive time +* zone transitions (e.g. when the daylight saving time starts or the time zone +* offset is increased due to a time zone rule change). +* @param duplicatedTimeOpt The option to indicate how to interpret the date and +* time in the calendar represent a local time that repeating multiple times at a +* negative time zone transition (e.g. when the daylight saving time ends or the +* time zone offset is decreased due to a time zone rule change) +* @param rawOffset output parameter to receive the raw offset, that +* is, the offset not including DST adjustments. +* If the status is set to one of the error code, the value set is unspecified. +* @param dstOffset output parameter to receive the DST offset, +* that is, the offset to be added to `rawOffset' to obtain the +* total offset between local and GMT time. If DST is not in +* effect, this value is zero; otherwise it is a positive value, +* typically one hour. +* If the status is set to one of the error code, the value set is unspecified. +* @param status A pointer to a UErrorCode to receive any errors. +* @draft ICU 69 +*/ +U_CAPI void U_EXPORT2 +ucal_getTimeZoneOffsetFromLocal( + const UCalendar* cal, + UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, + int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status); +#endif /* U_FORCE_HIDE_DRAFT_API */ + #endif /* #if !UCONFIG_NO_FORMATTING */ #endif diff --git a/icu4c/source/i18n/unicode/vtzone.h b/icu4c/source/i18n/unicode/vtzone.h index 383b8da23f8..bb7a5a827ef 100644 --- a/icu4c/source/i18n/unicode/vtzone.h +++ b/icu4c/source/i18n/unicode/vtzone.h @@ -264,6 +264,17 @@ public: virtual void getOffset(UDate date, UBool local, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& ec) const; + #ifndef U_FORCE_HIDE_DRAFT_API + /** + * Get time zone offsets from local wall time. + * @draft ICU 69 + */ + virtual void getOffsetFromLocal( + UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, + int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const; +#endif /* U_FORCE_HIDE_DRAFT_API */ + /** * Sets the TimeZone's raw GMT offset (i.e., the number of milliseconds to add * to GMT to get local time, before taking daylight savings time into account). diff --git a/icu4c/source/i18n/vtzone.cpp b/icu4c/source/i18n/vtzone.cpp index 8b9fdec0afe..2df91163bf4 100644 --- a/icu4c/source/i18n/vtzone.cpp +++ b/icu4c/source/i18n/vtzone.cpp @@ -1217,6 +1217,12 @@ VTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset, return tz->getOffset(date, local, rawOffset, dstOffset, status); } +void VTimeZone::getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + UTimeZoneLocalOption duplicatedTimeOpt, + int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const { + tz->getOffsetFromLocal(date, nonExistingTimeOpt, duplicatedTimeOpt, rawOffset, dstOffset, status); +} + void VTimeZone::setRawOffset(int32_t offsetMillis) { tz->setRawOffset(offsetMillis); diff --git a/icu4c/source/test/cintltst/ccaltst.c b/icu4c/source/test/cintltst/ccaltst.c index da7d1a6b965..13bede20a71 100644 --- a/icu4c/source/test/cintltst/ccaltst.c +++ b/icu4c/source/test/cintltst/ccaltst.c @@ -41,6 +41,7 @@ void TestGetWindowsTimeZoneID(void); void TestGetTimeZoneIDByWindowsID(void); void TestJpnCalAddSetNextEra(void); void TestUcalOpenBufferRead(void); +void TestGetTimeZoneOffsetFromLocal(void); void addCalTest(TestNode** root); @@ -65,6 +66,7 @@ void addCalTest(TestNode** root) addTest(root, &TestGetTimeZoneIDByWindowsID, "tsformat/ccaltst/TestGetTimeZoneIDByWindowsID"); addTest(root, &TestJpnCalAddSetNextEra, "tsformat/ccaltst/TestJpnCalAddSetNextEra"); addTest(root, &TestUcalOpenBufferRead, "tsformat/ccaltst/TestUcalOpenBufferRead"); + addTest(root, &TestGetTimeZoneOffsetFromLocal, "tsformat/ccaltst/TestGetTimeZoneOffsetFromLocal"); } /* "GMT" */ @@ -2553,4 +2555,220 @@ void TestUcalOpenBufferRead() { ucal_close(cal); } + +/* + * Testing ucal_getTimeZoneOffsetFromLocal + */ +void +TestGetTimeZoneOffsetFromLocal() { + static const UChar utc[] = u"Etc/GMT"; + + const int32_t HOUR = 60*60*1000; + const int32_t MINUTE = 60*1000; + + const int32_t DATES[][6] = { + {2006, UCAL_APRIL, 2, 1, 30, 1*HOUR+30*MINUTE}, + {2006, UCAL_APRIL, 2, 2, 00, 2*HOUR}, + {2006, UCAL_APRIL, 2, 2, 30, 2*HOUR+30*MINUTE}, + {2006, UCAL_APRIL, 2, 3, 00, 3*HOUR}, + {2006, UCAL_APRIL, 2, 3, 30, 3*HOUR+30*MINUTE}, + {2006, UCAL_OCTOBER, 29, 0, 30, 0*HOUR+30*MINUTE}, + {2006, UCAL_OCTOBER, 29, 1, 00, 1*HOUR}, + {2006, UCAL_OCTOBER, 29, 1, 30, 1*HOUR+30*MINUTE}, + {2006, UCAL_OCTOBER, 29, 2, 00, 2*HOUR}, + {2006, UCAL_OCTOBER, 29, 2, 30, 2*HOUR+30*MINUTE}, + }; + + // Expected offsets by + // void U_ucal_getTimeZoneOffsetFromLocal( + // const UCalendar* cal, + // UTimeZoneLocalOption nonExistingTimeOpt, + // UTimeZoneLocalOption duplicatedTimeOpt, + // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status); + // with nonExistingTimeOpt=UCAL_TZ_LOCAL_STANDARD and + // duplicatedTimeOpt=UCAL_TZ_LOCAL_STANDARD + const int32_t OFFSETS2[][2] = { + // April 2, 2006 + {-8*HOUR, 0}, + {-8*HOUR, 0}, + {-8*HOUR, 0}, + {-8*HOUR, 1*HOUR}, + {-8*HOUR, 1*HOUR}, + + // Oct 29, 2006 + {-8*HOUR, 1*HOUR}, + {-8*HOUR, 0}, + {-8*HOUR, 0}, + {-8*HOUR, 0}, + {-8*HOUR, 0}, + }; + + // Expected offsets by + // void U_ucal_getTimeZoneOffsetFromLocal( + // const UCalendar* cal, + // UTimeZoneLocalOption nonExistingTimeOpt, + // UTimeZoneLocalOption duplicatedTimeOpt, + // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status); + // with nonExistingTimeOpt=UCAL_TZ_LOCAL_DAYLIGHT and + // duplicatedTimeOpt=UCAL_TZ_LOCAL_DAYLIGHT + const int32_t OFFSETS3[][2] = { + // April 2, 2006 + {-8*HOUR, 0}, + {-8*HOUR, 1*HOUR}, + {-8*HOUR, 1*HOUR}, + {-8*HOUR, 1*HOUR}, + {-8*HOUR, 1*HOUR}, + + // October 29, 2006 + {-8*HOUR, 1*HOUR}, + {-8*HOUR, 1*HOUR}, + {-8*HOUR, 1*HOUR}, + {-8*HOUR, 0}, + {-8*HOUR, 0}, + }; + + UErrorCode status = U_ZERO_ERROR; + + int32_t rawOffset, dstOffset; + UCalendar *cal = ucal_open(utc, -1, "en", UCAL_GREGORIAN, &status); + if (U_FAILURE(status)) { + log_data_err("ucal_open: %s", u_errorName(status)); + return; + } + + // Calculate millis + UDate MILLIS[UPRV_LENGTHOF(DATES)]; + for (int32_t i = 0; i < UPRV_LENGTHOF(DATES); i++) { + ucal_setDateTime(cal, DATES[i][0], DATES[i][1], DATES[i][2], + DATES[i][3], DATES[i][4], 0, &status); + MILLIS[i] = ucal_getMillis(cal, &status); + if (U_FAILURE(status)) { + log_data_err("ucal_getMillis failed"); + return; + } + } + ucal_setTimeZone(cal, AMERICA_LOS_ANGELES, -1, &status); + + // Test void ucal_getTimeZoneOffsetFromLocal( + // const UCalendar* cal, + // UTimeZoneLocalOption nonExistingTimeOpt, + // UTimeZoneLocalOption duplicatedTimeOpt, + // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status); + // with nonExistingTimeOpt=UCAL_TZ_LOCAL_STANDARD and + // duplicatedTimeOpt=UCAL_TZ_LOCAL_STANDARD + for (int m = 0; m < UPRV_LENGTHOF(DATES); m++) { + status = U_ZERO_ERROR; + ucal_setMillis(cal, MILLIS[m], &status); + if (U_FAILURE(status)) { + log_data_err("ucal_setMillis: %s\n", u_errorName(status)); + } + + ucal_getTimeZoneOffsetFromLocal(cal, UCAL_TZ_LOCAL_STANDARD_FORMER, UCAL_TZ_LOCAL_STANDARD_LATTER, + &rawOffset, &dstOffset, &status); + if (U_FAILURE(status)) { + log_err("ERROR: ucal_getTimeZoneOffsetFromLocal((%d-%d-%d %d:%d:0)," + "UCAL_TZ_LOCAL_STANDARD_FORMER, UCAL_TZ_LOCAL_STANDARD_LATTER: %s\n", + DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4], + u_errorName(status)); + } else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) { + log_err("Bad offset returned at (%d-%d-%d %d:%d:0) " + "(wall/UCAL_TZ_LOCAL_STANDARD_FORMER/UCAL_TZ_LOCAL_STANDARD_LATTER) \n- Got: %d / %d " + " Expected %d / %d\n", + DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4], + rawOffset, dstOffset, OFFSETS2[m][0], OFFSETS2[m][1]); + } + } + + // Test void ucal_getTimeZoneOffsetFromLocal( + // const UCalendar* cal, + // UTimeZoneLocalOption nonExistingTimeOpt, + // UTimeZoneLocalOption duplicatedTimeOpt, + // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status); + // with nonExistingTimeOpt=UCAL_TZ_LOCAL_DAYLIGHT and + // duplicatedTimeOpt=UCAL_TZ_LOCAL_DAYLIGHT + for (int m = 0; m < UPRV_LENGTHOF(DATES); m++) { + status = U_ZERO_ERROR; + ucal_setMillis(cal, MILLIS[m], &status); + if (U_FAILURE(status)) { + log_data_err("ucal_setMillis: %s\n", u_errorName(status)); + } + + ucal_getTimeZoneOffsetFromLocal(cal, UCAL_TZ_LOCAL_DAYLIGHT_LATTER, UCAL_TZ_LOCAL_DAYLIGHT_FORMER, + &rawOffset, &dstOffset, &status); + if (U_FAILURE(status)) { + log_err("ERROR: ucal_getTimeZoneOffsetFromLocal((%d-%d-%d %d:%d:0)," + "UCAL_TZ_LOCAL_DAYLIGHT_LATTER, UCAL_TZ_LOCAL_DAYLIGHT_FORMER: %s\n", + DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4], + u_errorName(status)); + } else if (rawOffset != OFFSETS3[m][0] || dstOffset != OFFSETS3[m][1]) { + log_err("Bad offset returned at (%d-%d-%d %d:%d:0) " + "(wall/UCAL_TZ_LOCAL_DAYLIGHT_LATTER/UCAL_TZ_LOCAL_DAYLIGHT_FORMER) \n- Got: %d / %d " + " Expected %d / %d\n", + DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4], + rawOffset, dstOffset, OFFSETS3[m][0], OFFSETS3[m][1]); + } + } + + // Test void ucal_getTimeZoneOffsetFromLocal( + // const UCalendar* cal, + // UTimeZoneLocalOption nonExistingTimeOpt, + // UTimeZoneLocalOption duplicatedTimeOpt, + // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status); + // with nonExistingTimeOpt=UCAL_TZ_LOCAL_FORMER and + // duplicatedTimeOpt=UCAL_TZ_LOCAL_LATTER + for (int m = 0; m < UPRV_LENGTHOF(DATES); m++) { + status = U_ZERO_ERROR; + ucal_setMillis(cal, MILLIS[m], &status); + if (U_FAILURE(status)) { + log_data_err("ucal_setMillis: %s\n", u_errorName(status)); + } + + ucal_getTimeZoneOffsetFromLocal(cal, UCAL_TZ_LOCAL_FORMER, UCAL_TZ_LOCAL_LATTER, + &rawOffset, &dstOffset, &status); + if (U_FAILURE(status)) { + log_err("ERROR: ucal_getTimeZoneOffsetFromLocal((%d-%d-%d %d:%d:0)," + "UCAL_TZ_LOCAL_FORMER, UCAL_TZ_LOCAL_LATTER: %s\n", + DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4], + u_errorName(status)); + } else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) { + log_err("Bad offset returned at (%d-%d-%d %d:%d:0) " + "(wall/UCAL_TZ_LOCAL_FORMER/UCAL_TZ_LOCAL_LATTER) \n- Got: %d / %d " + " Expected %d / %d\n", + DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4], + rawOffset, dstOffset, OFFSETS2[m][0], OFFSETS2[m][1]); + } + } + + // Test void ucal_getTimeZoneOffsetFromLocal( + // const UCalendar* cal, + // UTimeZoneLocalOption nonExistingTimeOpt, + // UTimeZoneLocalOption duplicatedTimeOpt, + // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status); + // with nonExistingTimeOpt=UCAL_TZ_LOCAL_LATTER and + // duplicatedTimeOpt=UCAL_TZ_LOCAL_FORMER + for (int m = 0; m < UPRV_LENGTHOF(DATES); m++) { + status = U_ZERO_ERROR; + ucal_setMillis(cal, MILLIS[m], &status); + if (U_FAILURE(status)) { + log_data_err("ucal_setMillis: %s\n", u_errorName(status)); + } + + ucal_getTimeZoneOffsetFromLocal(cal, UCAL_TZ_LOCAL_LATTER, UCAL_TZ_LOCAL_FORMER, + &rawOffset, &dstOffset, &status); + if (U_FAILURE(status)) { + log_err("ERROR: ucal_getTimeZoneOffsetFromLocal((%d-%d-%d %d:%d:0)," + "UCAL_TZ_LOCAL_LATTER, UCAL_TZ_LOCAL_FORMER: %s\n", + DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4], + u_errorName(status)); + } else if (rawOffset != OFFSETS3[m][0] || dstOffset != OFFSETS3[m][1]) { + log_err("Bad offset returned at (%d-%d-%d %d:%d:0) " + "(wall/UCAL_TZ_LOCAL_LATTER/UCAL_TZ_LOCAL_FORMER) \n- Got: %d / %d " + " Expected %d / %d\n", + DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4], + rawOffset, dstOffset, OFFSETS3[m][0], OFFSETS3[m][1]); + } + } + ucal_close(cal); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/test/intltest/tzoffloc.cpp b/icu4c/source/test/intltest/tzoffloc.cpp index 1402469507b..d567cb99ac0 100644 --- a/icu4c/source/test/intltest/tzoffloc.cpp +++ b/icu4c/source/test/intltest/tzoffloc.cpp @@ -79,9 +79,9 @@ TimeZoneOffsetLocalTest::TestGetOffsetAroundTransition() { // Expected offsets by void getOffset(UDate date, UBool local, int32_t& rawOffset, // int32_t& dstOffset, UErrorCode& ec) with local=TRUE - // or void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + // or void getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, // int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) with - // nonExistingTimeOpt=kStandard/duplicatedTimeOpt=kStandard + // nonExistingTimeOpt=STANDARD_*/duplicatedTimeOpt=STANDARD_* const int32_t OFFSETS2[NUM_DATES][2] = { // April 2, 2006 {-8*HOUR, 0}, @@ -98,9 +98,9 @@ TimeZoneOffsetLocalTest::TestGetOffsetAroundTransition() { {-8*HOUR, 0}, }; - // Expected offsets by void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, - // int32_t duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) with - // nonExistingTimeOpt=kDaylight/duplicatedTimeOpt=kDaylight + // Expected offsets by void getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, + // UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) with + // nonExistingTimeOpt=DAYLIGHT_*/duplicatedTimeOpt=DAYLIGHT_* const int32_t OFFSETS3[][2] = { // April 2, 2006 {-8*HOUR, 0}, @@ -237,84 +237,84 @@ TimeZoneOffsetLocalTest::TestGetOffsetAroundTransition() { } } - // Test getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + // Test getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, // int32_t& rawOffset, int32_t& dstOffset, UErroCode& status) - // with nonExistingTimeOpt=kStandard/duplicatedTimeOpt=kStandard + // with nonExistingTimeOpt=STANDARD_FORMER/duplicatedTimeOpt=STANDARD_LATTER for (int32_t i = 0; i < NUM_TIMEZONES; i++) { for (int m = 0; m < NUM_DATES; m++) { status = U_ZERO_ERROR; - TESTZONES[i]->getOffsetFromLocal(MILLIS[m], BasicTimeZone::kStandard, BasicTimeZone::kStandard, + TESTZONES[i]->getOffsetFromLocal(MILLIS[m], UCAL_TZ_LOCAL_STANDARD_FORMER, UCAL_TZ_LOCAL_STANDARD_LATTER, rawOffset, dstOffset, status); if (U_FAILURE(status)) { - errln((UnicodeString)"getOffsetFromLocal with kStandard/kStandard failed for TESTZONES[" + i + "]"); + errln((UnicodeString)"getOffsetFromLocal with UCAL_TZ_LOCAL_STANDARD_FORMER/UCAL_TZ_LOCAL_STANDARD_LATTER failed for TESTZONES[" + i + "]"); } else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) { dateStr.remove(); df.format(MILLIS[m], dateStr); dataerrln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at " - + dateStr + "(wall/kStandard/kStandard) - Got: " + + dateStr + "(wall/STANDARD_FORMER/STANDARD_LATTER) - Got: " + rawOffset + "/" + dstOffset + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]); } } } - // Test getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + // Test getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, // int32_t& rawOffset, int32_t& dstOffset, UErroCode& status) - // with nonExistingTimeOpt=kDaylight/duplicatedTimeOpt=kDaylight + // with nonExistingTimeOpt=DAYLIGHT_LATTER/duplicatedTimeOpt=DAYLIGHT_FORMER for (int32_t i = 0; i < NUM_TIMEZONES; i++) { for (int m = 0; m < NUM_DATES; m++) { status = U_ZERO_ERROR; - TESTZONES[i]->getOffsetFromLocal(MILLIS[m], BasicTimeZone::kDaylight, BasicTimeZone::kDaylight, + TESTZONES[i]->getOffsetFromLocal(MILLIS[m], UCAL_TZ_LOCAL_DAYLIGHT_LATTER, UCAL_TZ_LOCAL_DAYLIGHT_FORMER, rawOffset, dstOffset, status); if (U_FAILURE(status)) { - errln((UnicodeString)"getOffsetFromLocal with kDaylight/kDaylight failed for TESTZONES[" + i + "]"); + errln((UnicodeString)"getOffsetFromLocal with UCAL_TZ_LOCAL_DAYLIGHT_LATTER/UCAL_TZ_LOCAL_DAYLIGHT_FORMER failed for TESTZONES[" + i + "]"); } else if (rawOffset != OFFSETS3[m][0] || dstOffset != OFFSETS3[m][1]) { dateStr.remove(); df.format(MILLIS[m], dateStr); dataerrln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at " - + dateStr + "(wall/kDaylight/kDaylight) - Got: " + + dateStr + "(wall/DAYLIGHT_LATTER/DAYLIGHT_FORMER) - Got: " + rawOffset + "/" + dstOffset + " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]); } } } - // Test getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + // Test getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, // int32_t& rawOffset, int32_t& dstOffset, UErroCode& status) - // with nonExistingTimeOpt=kFormer/duplicatedTimeOpt=kLatter + // with nonExistingTimeOpt=FORMER/duplicatedTimeOpt=LATTER for (int32_t i = 0; i < NUM_TIMEZONES; i++) { for (int m = 0; m < NUM_DATES; m++) { status = U_ZERO_ERROR; - TESTZONES[i]->getOffsetFromLocal(MILLIS[m], BasicTimeZone::kFormer, BasicTimeZone::kLatter, + TESTZONES[i]->getOffsetFromLocal(MILLIS[m], UCAL_TZ_LOCAL_FORMER, UCAL_TZ_LOCAL_LATTER, rawOffset, dstOffset, status); if (U_FAILURE(status)) { - errln((UnicodeString)"getOffsetFromLocal with kFormer/kLatter failed for TESTZONES[" + i + "]"); + errln((UnicodeString)"getOffsetFromLocal with UCAL_TZ_LOCAL_FORMER/UCAL_TZ_LOCAL_LATTER failed for TESTZONES[" + i + "]"); } else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) { dateStr.remove(); df.format(MILLIS[m], dateStr); dataerrln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at " - + dateStr + "(wall/kFormer/kLatter) - Got: " + + dateStr + "(wall/FORMER/LATTER) - Got: " + rawOffset + "/" + dstOffset + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]); } } } - // Test getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, + // Test getOffsetFromLocal(UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, // int32_t& rawOffset, int32_t& dstOffset, UErroCode& status) - // with nonExistingTimeOpt=kLatter/duplicatedTimeOpt=kFormer + // with nonExistingTimeOpt=LATTER/duplicatedTimeOpt=FORMER for (int32_t i = 0; i < NUM_TIMEZONES; i++) { for (int m = 0; m < NUM_DATES; m++) { status = U_ZERO_ERROR; - TESTZONES[i]->getOffsetFromLocal(MILLIS[m], BasicTimeZone::kLatter, BasicTimeZone::kFormer, + TESTZONES[i]->getOffsetFromLocal(MILLIS[m], UCAL_TZ_LOCAL_LATTER, UCAL_TZ_LOCAL_FORMER, rawOffset, dstOffset, status); if (U_FAILURE(status)) { - errln((UnicodeString)"getOffsetFromLocal with kLatter/kFormer failed for TESTZONES[" + i + "]"); + errln((UnicodeString)"getOffsetFromLocal with UCAL_TZ_LOCAL_LATTER/UCAL_TZ_LOCAL_FORMER failed for TESTZONES[" + i + "]"); } else if (rawOffset != OFFSETS3[m][0] || dstOffset != OFFSETS3[m][1]) { dateStr.remove(); df.format(MILLIS[m], dateStr); dataerrln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at " - + dateStr + "(wall/kLatter/kFormer) - Got: " + + dateStr + "(wall/LATTER/FORMER) - Got: " + rawOffset + "/" + dstOffset + " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]); }