diff --git a/icu4c/source/i18n/ucal.cpp b/icu4c/source/i18n/ucal.cpp index e8f6d2e96f8..927b2d36979 100644 --- a/icu4c/source/i18n/ucal.cpp +++ b/icu4c/source/i18n/ucal.cpp @@ -34,7 +34,7 @@ U_NAMESPACE_USE static TimeZone* _createTimeZone(const UChar* zoneID, int32_t len, UErrorCode* ec) { TimeZone* zone = NULL; - if (ec!=NULL && U_SUCCESS(*ec)) { + if (ec != NULL && U_SUCCESS(*ec)) { // Note that if zoneID is invalid, we get back GMT. This odd // behavior is by design and goes back to the JDK. The only // failure we will see is a memory allocation failure. @@ -69,7 +69,7 @@ ucal_openCountryTimeZones(const char* country, UErrorCode* ec) { U_CAPI int32_t U_EXPORT2 ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec) { int32_t len = 0; - if (ec!=NULL && U_SUCCESS(*ec)) { + if (ec != NULL && U_SUCCESS(*ec)) { TimeZone* zone = TimeZone::createDefault(); if (zone == NULL) { *ec = U_MEMORY_ALLOCATION_ERROR; @@ -91,6 +91,23 @@ ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec) { } } +U_DRAFT int32_t U_EXPORT2 +ucal_getHostTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec) { + int32_t len = 0; + if (ec != NULL && U_SUCCESS(*ec)) { + TimeZone *zone = TimeZone::detectHostTimeZone(); + if (zone == NULL) { + *ec = U_MEMORY_ALLOCATION_ERROR; + } else { + UnicodeString id; + zone->getID(id); + delete zone; + len = id.extract(result, resultCapacity, *ec); + } + } + return len; +} + U_CAPI int32_t U_EXPORT2 ucal_getDSTSavings(const UChar* zoneID, UErrorCode* ec) { int32_t result = 0; diff --git a/icu4c/source/i18n/unicode/ucal.h b/icu4c/source/i18n/unicode/ucal.h index f31a25732dc..4466223bf0f 100644 --- a/icu4c/source/i18n/unicode/ucal.h +++ b/icu4c/source/i18n/unicode/ucal.h @@ -657,6 +657,42 @@ ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* ec); U_STABLE void U_EXPORT2 ucal_setDefaultTimeZone(const UChar* zoneID, UErrorCode* ec); +#ifndef U_HIDE_DRAFT_API + +/** + * Return the current host time zone. The host time zone is detected from + * the current host system configuration by querying the host operating + * system. If the host system detection routines fail, or if they specify + * a TimeZone or TimeZone offset which is not recognized, then the special + * TimeZone "Etc/Unknown" is returned. + * + * Note that host time zone and the ICU default time zone can be different. + * + * The ICU default time zone does not change once initialized unless modified + * by calling `ucal_setDefaultTimeZone()` or with the C++ TimeZone API, + * `TimeZone::adoptDefault(TimeZone*)`. + * + * If the host operating system configuration has changed since ICU has + * initialized then the returned value can be different than the ICU default + * time zone, even if the default has not changed. + * + *

This function is not thread safe.

+ * + * @param result A buffer to receive the result, or NULL + * @param resultCapacity The capacity of the result buffer + * @param ec input/output error code + * @return The result string length, not including the terminating + * null + * + * @see #UCAL_UNKNOWN_ZONE_ID + * + * @draft ICU 65 + */ +U_DRAFT int32_t U_EXPORT2 +ucal_getHostTimeZone(UChar *result, int32_t resultCapacity, UErrorCode *ec); + +#endif // U_HIDE_DRAFT_API + /** * Return the amount of time in milliseconds that the clock is * advanced during daylight savings time for the given time zone, or diff --git a/icu4c/source/test/cintltst/ccaltst.c b/icu4c/source/test/cintltst/ccaltst.c index 2ce054690d8..eaff8f3cd23 100644 --- a/icu4c/source/test/cintltst/ccaltst.c +++ b/icu4c/source/test/cintltst/ccaltst.c @@ -228,7 +228,7 @@ static void TestCalendar() log_err("FAIL: ucal_getDSTSavings(PST) => %d, expect %d\n", i, 1*60*60*1000); } - /*Test ucal_set/getDefaultTimeZone*/ + /*Test ucal_set/getDefaultTimeZone and ucal_getHostTimeZone */ status = U_ZERO_ERROR; i = ucal_getDefaultTimeZone(zone1, UPRV_LENGTHOF(zone1), &status); if (U_FAILURE(status)) { @@ -247,6 +247,16 @@ static void TestCalendar() } else { if (u_strcmp(zone2, EUROPE_PARIS) != 0) { log_data_err("FAIL: ucal_getDefaultTimeZone() did not return Europe/Paris (Are you missing data?)\n"); + } else { + // Redetect the host timezone, it should be the same as zone1 even though ICU's default timezone has been changed. + i = ucal_getHostTimeZone(zone2, UPRV_LENGTHOF(zone2), &status); + if (U_FAILURE(status)) { + log_err("FAIL: ucal_getHostTimeZone() => %s\n", u_errorName(status)); + } else { + if (u_strcmp(zone1, zone2) != 0) { + log_err("FAIL: ucal_getHostTimeZone() should give the same host timezone even if the default changed.\n"); + } + } } } }