blob: e31679562be92620d36587fc080198d0b3ea9f45 [file] [log] [blame]
diff --git a/source/i18n/timezone.cpp b/source/i18n/timezone.cpp
index 6ed008d..6b3f8d2 100644
--- a/source/i18n/timezone.cpp
+++ b/source/i18n/timezone.cpp
@@ -1,6 +1,6 @@
/*
*******************************************************************************
-* Copyright (C) 1997-2014, International Business Machines Corporation and
+* Copyright (C) 1997-2015, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
@@ -440,21 +440,9 @@ TimeZone::createTimeZone(const UnicodeString& ID)
// -------------------------------------
-/**
- * Initialize DEFAULT_ZONE from the system default time zone.
- * Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
- * returns NULL.
- */
-static void U_CALLCONV initDefault()
+TimeZone* U_EXPORT2
+TimeZone::detectHostTimeZone()
{
- ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
-
- // If setDefault() has already been called we can skip getting the
- // default zone information from the system.
- if (DEFAULT_ZONE != NULL) {
- return;
- }
-
// We access system timezone data through TPlatformUtilities,
// including tzset(), timezone, and tzname[].
int32_t rawOffset = 0;
@@ -463,16 +451,6 @@ static void U_CALLCONV initDefault()
// First, try to create a system timezone, based
// on the string ID in tzname[0].
- // NOTE: this code is safely single threaded, being only
- // run via umtx_initOnce().
- //
- // Some of the locale/timezone OS functions may not be thread safe,
- //
- // The operating system might actually use ICU to implement timezones.
- // So we may have ICU calling ICU here, like on AIX.
- // There shouldn't be a problem with this; initOnce does not hold a mutex
- // while the init function is being run.
-
uprv_tzset(); // Initialize tz... system data
// Get the timezone ID from the host. This function should do
@@ -484,13 +462,13 @@ static void U_CALLCONV initDefault()
// Invert sign because UNIX semantics are backwards
rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND;
- TimeZone* default_zone = NULL;
+ TimeZone* hostZone = NULL;
/* Make sure that the string is NULL terminated to prevent BoundsChecker/Purify warnings. */
UnicodeString hostStrID(hostID, -1, US_INV);
hostStrID.append((UChar)0);
hostStrID.truncate(hostStrID.length()-1);
- default_zone = createSystemTimeZone(hostStrID);
+ hostZone = createSystemTimeZone(hostStrID);
#if U_PLATFORM_USES_ONLY_WIN32_API
// hostID points to a heap-allocated location on Windows.
@@ -498,30 +476,69 @@ static void U_CALLCONV initDefault()
#endif
int32_t hostIDLen = hostStrID.length();
- if (default_zone != NULL && rawOffset != default_zone->getRawOffset()
+ if (hostZone != NULL && rawOffset != hostZone->getRawOffset()
&& (3 <= hostIDLen && hostIDLen <= 4))
{
// Uh oh. This probably wasn't a good id.
// It was probably an ambiguous abbreviation
- delete default_zone;
- default_zone = NULL;
+ delete hostZone;
+ hostZone = NULL;
}
// Construct a fixed standard zone with the host's ID
// and raw offset.
- if (default_zone == NULL) {
- default_zone = new SimpleTimeZone(rawOffset, hostStrID);
+ if (hostZone == NULL) {
+ hostZone = new SimpleTimeZone(rawOffset, hostStrID);
}
// If we _still_ don't have a time zone, use GMT.
- if (default_zone == NULL) {
+ //
+ // Note: This is extremely unlikely situation. If
+ // new SimpleTimeZone(...) above fails, the following
+ // code may also fail.
+ if (hostZone == NULL) {
const TimeZone* temptz = TimeZone::getGMT();
// If we can't use GMT, get out.
if (temptz == NULL) {
- return;
+ return NULL;
}
- default_zone = temptz->clone();
+ hostZone = temptz->clone();
+ }
+
+ return hostZone;
+}
+
+// -------------------------------------
+
+/**
+ * Initialize DEFAULT_ZONE from the system default time zone.
+ * Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
+ * returns NULL.
+ */
+static void U_CALLCONV initDefault()
+{
+ ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
+
+ // If setDefault() has already been called we can skip getting the
+ // default zone information from the system.
+ if (DEFAULT_ZONE != NULL) {
+ return;
}
+
+ // NOTE: this code is safely single threaded, being only
+ // run via umtx_initOnce().
+ //
+ // Some of the locale/timezone OS functions may not be thread safe,
+ //
+ // The operating system might actually use ICU to implement timezones.
+ // So we may have ICU calling ICU here, like on AIX.
+ // There shouldn't be a problem with this; initOnce does not hold a mutex
+ // while the init function is being run.
+
+ // The code detecting the host time zone was separated from this
+ // and implemented as TimeZone::detectHostTimeZone()
+
+ TimeZone *default_zone = TimeZone::detectHostTimeZone();
// The only way for DEFAULT_ZONE to be non-null at this point is if the user
// made a thread-unsafe call to setDefault() or adoptDefault() in another
diff --git a/source/i18n/unicode/timezone.h b/source/i18n/unicode/timezone.h
index fa4f5bf..c3356c9 100644
--- a/source/i18n/unicode/timezone.h
+++ b/source/i18n/unicode/timezone.h
@@ -1,5 +1,5 @@
/*************************************************************************
-* Copyright (c) 1997-2014, International Business Machines Corporation
+* Copyright (c) 1997-2015, International Business Machines Corporation
* and others. All Rights Reserved.
**************************************************************************
*
@@ -273,6 +273,23 @@ public:
static const UnicodeString U_EXPORT2 getEquivalentID(const UnicodeString& id,
int32_t index);
+#ifndef U_HIDE_DRAFT_API
+ /**
+ * Creates an instance of TimeZone detected from the current host
+ * system configuration. Note that ICU4C does not change the default
+ * time zone unless TimeZone::adoptDefault(TimeZone*) or
+ * TimeZone::setDefault(const TimeZone&) is explicitly called by a
+ * user. This method does not update the current ICU's default,
+ * and may return a different TimeZone from the one returned by
+ * TimeZone::createDefault().
+ *
+ * @return A new instance of TimeZone detected from the current host system
+ * configuration.
+ * @draft ICU 55
+ */
+ static TimeZone* U_EXPORT2 detectHostTimeZone();
+#endif
+
/**
* Creates a new copy of the default TimeZone for this host. Unless the default time
* zone has already been set using adoptDefault() or setDefault(), the default is
diff --git a/source/test/intltest/tztest.cpp b/source/test/intltest/tztest.cpp
index 4111e51..76304e9 100644
--- a/source/test/intltest/tztest.cpp
+++ b/source/test/intltest/tztest.cpp
@@ -135,6 +135,13 @@ TimeZoneTest::TestGenericAPI()
infoln("WARNING: t_timezone may be incorrect. It is not a multiple of 15min.", tzoffset);
}
+ TimeZone* hostZone = TimeZone::detectHostTimeZone();
+ /* Host time zone's offset should match the offset returned by uprv_timezone() */
+ if (hostZone->getRawOffset() != tzoffset * (-1000)) {
+ errln("FAIL: detectHostTimeZone()'s raw offset != host timezone's offset");
+ }
+ delete hostZone;
+
UErrorCode status = U_ZERO_ERROR;
const char* tzver = TimeZone::getTZDataVersion(status);
if (U_FAILURE(status)) {