| OLD | NEW |
| 1 diff --git a/source/common/putil.cpp b/source/common/putil.cpp |
| 2 index 5f09288..c87b60e 100644 |
| 3 --- a/source/common/putil.cpp |
| 4 +++ b/source/common/putil.cpp |
| 5 @@ -970,6 +970,15 @@ static char* searchForTZFile(const char* path, DefaultTZInf
o* tzInfo) { |
| 6 return result; |
| 7 } |
| 8 #endif |
| 9 + |
| 10 +U_CAPI void U_EXPORT2 |
| 11 +uprv_tzname_clear_cache() |
| 12 +{ |
| 13 +#if defined(CHECK_LOCALTIME_LINK) && !defined(DEBUG_SKIP_LOCALTIME_LINK) |
| 14 + gTimeZoneBufferPtr = NULL; |
| 15 +#endif |
| 16 +} |
| 17 + |
| 18 U_CAPI const char* U_EXPORT2 |
| 19 uprv_tzname(int n) |
| 20 { |
| 21 diff --git a/source/common/putilimp.h b/source/common/putilimp.h |
| 22 index 5de801f..55ec0ae 100644 |
| 23 --- a/source/common/putilimp.h |
| 24 +++ b/source/common/putilimp.h |
| 25 @@ -479,6 +479,12 @@ U_INTERNAL int32_t U_EXPORT2 uprv_timezone(void); |
| 26 U_INTERNAL const char* U_EXPORT2 uprv_tzname(int n); |
| 27 |
| 28 /** |
| 29 + * Reset the global tzname cache. |
| 30 + * @internal |
| 31 + */ |
| 32 +U_INTERNAL void uprv_tzname_clear_cache(); |
| 33 + |
| 34 +/** |
| 35 * Get UTC (GMT) time measured in milliseconds since 0:00 on 1/1/1970. |
| 36 * This function is affected by 'faketime' and should be the bottleneck for all
user-visible ICU time functions. |
| 37 * @return the UTC time measured in milliseconds |
| 1 diff --git a/source/i18n/timezone.cpp b/source/i18n/timezone.cpp | 38 diff --git a/source/i18n/timezone.cpp b/source/i18n/timezone.cpp |
| 2 index 6ed008d..6b3f8d2 100644 | 39 index 59c3891..00eca38 100644 |
| 3 --- a/source/i18n/timezone.cpp | 40 --- a/source/i18n/timezone.cpp |
| 4 +++ b/source/i18n/timezone.cpp | 41 +++ b/source/i18n/timezone.cpp |
| 5 @@ -1,6 +1,6 @@ | 42 @@ -458,6 +458,8 @@ TimeZone::detectHostTimeZone() |
| 6 /* | |
| 7 ******************************************************************************* | |
| 8 -* Copyright (C) 1997-2014, International Business Machines Corporation and | |
| 9 +* Copyright (C) 1997-2015, International Business Machines Corporation and | |
| 10 * others. All Rights Reserved. | |
| 11 ******************************************************************************* | |
| 12 * | |
| 13 @@ -440,21 +440,9 @@ TimeZone::createTimeZone(const UnicodeString& ID) | |
| 14 | 43 |
| 15 // ------------------------------------- | |
| 16 | |
| 17 -/** | |
| 18 - * Initialize DEFAULT_ZONE from the system default time zone. | |
| 19 - * Upon return, DEFAULT_ZONE will not be NULL, unless operator new() | |
| 20 - * returns NULL. | |
| 21 - */ | |
| 22 -static void U_CALLCONV initDefault() | |
| 23 +TimeZone* U_EXPORT2 | |
| 24 +TimeZone::detectHostTimeZone() | |
| 25 { | |
| 26 - ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup); | |
| 27 - | |
| 28 - // If setDefault() has already been called we can skip getting the | |
| 29 - // default zone information from the system. | |
| 30 - if (DEFAULT_ZONE != NULL) { | |
| 31 - return; | |
| 32 - } | |
| 33 - | |
| 34 // We access system timezone data through TPlatformUtilities, | |
| 35 // including tzset(), timezone, and tzname[]. | |
| 36 int32_t rawOffset = 0; | |
| 37 @@ -463,16 +451,6 @@ static void U_CALLCONV initDefault() | |
| 38 // First, try to create a system timezone, based | |
| 39 // on the string ID in tzname[0]. | |
| 40 | |
| 41 - // NOTE: this code is safely single threaded, being only | |
| 42 - // run via umtx_initOnce(). | |
| 43 - // | |
| 44 - // Some of the locale/timezone OS functions may not be thread safe, | |
| 45 - // | |
| 46 - // The operating system might actually use ICU to implement timezones. | |
| 47 - // So we may have ICU calling ICU here, like on AIX. | |
| 48 - // There shouldn't be a problem with this; initOnce does not hold a mutex | |
| 49 - // while the init function is being run. | |
| 50 - | |
| 51 uprv_tzset(); // Initialize tz... system data | 44 uprv_tzset(); // Initialize tz... system data |
| 52 | 45 |
| 46 + uprv_tzname_clear_cache(); |
| 47 + |
| 53 // Get the timezone ID from the host. This function should do | 48 // Get the timezone ID from the host. This function should do |
| 54 @@ -484,13 +462,13 @@ static void U_CALLCONV initDefault() | 49 // any required host-specific remapping; e.g., on Windows this |
| 55 // Invert sign because UNIX semantics are backwards | 50 // function maps the Date and Time control panel setting to an |
| 56 rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND; | |
| 57 | |
| 58 - TimeZone* default_zone = NULL; | |
| 59 + TimeZone* hostZone = NULL; | |
| 60 | |
| 61 /* Make sure that the string is NULL terminated to prevent BoundsChecker/Pu
rify warnings. */ | |
| 62 UnicodeString hostStrID(hostID, -1, US_INV); | |
| 63 hostStrID.append((UChar)0); | |
| 64 hostStrID.truncate(hostStrID.length()-1); | |
| 65 - default_zone = createSystemTimeZone(hostStrID); | |
| 66 + hostZone = createSystemTimeZone(hostStrID); | |
| 67 | |
| 68 #if U_PLATFORM_USES_ONLY_WIN32_API | |
| 69 // hostID points to a heap-allocated location on Windows. | |
| 70 @@ -498,30 +476,69 @@ static void U_CALLCONV initDefault() | |
| 71 #endif | |
| 72 | |
| 73 int32_t hostIDLen = hostStrID.length(); | |
| 74 - if (default_zone != NULL && rawOffset != default_zone->getRawOffset() | |
| 75 + if (hostZone != NULL && rawOffset != hostZone->getRawOffset() | |
| 76 && (3 <= hostIDLen && hostIDLen <= 4)) | |
| 77 { | |
| 78 // Uh oh. This probably wasn't a good id. | |
| 79 // It was probably an ambiguous abbreviation | |
| 80 - delete default_zone; | |
| 81 - default_zone = NULL; | |
| 82 + delete hostZone; | |
| 83 + hostZone = NULL; | |
| 84 } | |
| 85 | |
| 86 // Construct a fixed standard zone with the host's ID | |
| 87 // and raw offset. | |
| 88 - if (default_zone == NULL) { | |
| 89 - default_zone = new SimpleTimeZone(rawOffset, hostStrID); | |
| 90 + if (hostZone == NULL) { | |
| 91 + hostZone = new SimpleTimeZone(rawOffset, hostStrID); | |
| 92 } | |
| 93 | |
| 94 // If we _still_ don't have a time zone, use GMT. | |
| 95 - if (default_zone == NULL) { | |
| 96 + // | |
| 97 + // Note: This is extremely unlikely situation. If | |
| 98 + // new SimpleTimeZone(...) above fails, the following | |
| 99 + // code may also fail. | |
| 100 + if (hostZone == NULL) { | |
| 101 const TimeZone* temptz = TimeZone::getGMT(); | |
| 102 // If we can't use GMT, get out. | |
| 103 if (temptz == NULL) { | |
| 104 - return; | |
| 105 + return NULL; | |
| 106 } | |
| 107 - default_zone = temptz->clone(); | |
| 108 + hostZone = temptz->clone(); | |
| 109 + } | |
| 110 + | |
| 111 + return hostZone; | |
| 112 +} | |
| 113 + | |
| 114 +// ------------------------------------- | |
| 115 + | |
| 116 +/** | |
| 117 + * Initialize DEFAULT_ZONE from the system default time zone. | |
| 118 + * Upon return, DEFAULT_ZONE will not be NULL, unless operator new() | |
| 119 + * returns NULL. | |
| 120 + */ | |
| 121 +static void U_CALLCONV initDefault() | |
| 122 +{ | |
| 123 + ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup); | |
| 124 + | |
| 125 + // If setDefault() has already been called we can skip getting the | |
| 126 + // default zone information from the system. | |
| 127 + if (DEFAULT_ZONE != NULL) { | |
| 128 + return; | |
| 129 } | |
| 130 + | |
| 131 + // NOTE: this code is safely single threaded, being only | |
| 132 + // run via umtx_initOnce(). | |
| 133 + // | |
| 134 + // Some of the locale/timezone OS functions may not be thread safe, | |
| 135 + // | |
| 136 + // The operating system might actually use ICU to implement timezones. | |
| 137 + // So we may have ICU calling ICU here, like on AIX. | |
| 138 + // There shouldn't be a problem with this; initOnce does not hold a mutex | |
| 139 + // while the init function is being run. | |
| 140 + | |
| 141 + // The code detecting the host time zone was separated from this | |
| 142 + // and implemented as TimeZone::detectHostTimeZone() | |
| 143 + | |
| 144 + TimeZone *default_zone = TimeZone::detectHostTimeZone(); | |
| 145 | |
| 146 // The only way for DEFAULT_ZONE to be non-null at this point is if the use
r | |
| 147 // made a thread-unsafe call to setDefault() or adoptDefault() in another | |
| 148 diff --git a/source/i18n/unicode/timezone.h b/source/i18n/unicode/timezone.h | |
| 149 index fa4f5bf..c3356c9 100644 | |
| 150 --- a/source/i18n/unicode/timezone.h | |
| 151 +++ b/source/i18n/unicode/timezone.h | |
| 152 @@ -1,5 +1,5 @@ | |
| 153 /************************************************************************* | |
| 154 -* Copyright (c) 1997-2014, International Business Machines Corporation | |
| 155 +* Copyright (c) 1997-2015, International Business Machines Corporation | |
| 156 * and others. All Rights Reserved. | |
| 157 ************************************************************************** | |
| 158 * | |
| 159 @@ -273,6 +273,23 @@ public: | |
| 160 static const UnicodeString U_EXPORT2 getEquivalentID(const UnicodeString& i
d, | |
| 161 int32_t index); | |
| 162 | |
| 163 +#ifndef U_HIDE_DRAFT_API | |
| 164 + /** | |
| 165 + * Creates an instance of TimeZone detected from the current host | |
| 166 + * system configuration. Note that ICU4C does not change the default | |
| 167 + * time zone unless TimeZone::adoptDefault(TimeZone*) or | |
| 168 + * TimeZone::setDefault(const TimeZone&) is explicitly called by a | |
| 169 + * user. This method does not update the current ICU's default, | |
| 170 + * and may return a different TimeZone from the one returned by | |
| 171 + * TimeZone::createDefault(). | |
| 172 + * | |
| 173 + * @return A new instance of TimeZone detected from the current host syste
m | |
| 174 + * configuration. | |
| 175 + * @draft ICU 55 | |
| 176 + */ | |
| 177 + static TimeZone* U_EXPORT2 detectHostTimeZone(); | |
| 178 +#endif | |
| 179 + | |
| 180 /** | |
| 181 * Creates a new copy of the default TimeZone for this host. Unless the def
ault time | |
| 182 * zone has already been set using adoptDefault() or setDefault(), the defa
ult is | |
| 183 diff --git a/source/test/intltest/tztest.cpp b/source/test/intltest/tztest.cpp | |
| 184 index 4111e51..76304e9 100644 | |
| 185 --- a/source/test/intltest/tztest.cpp | |
| 186 +++ b/source/test/intltest/tztest.cpp | |
| 187 @@ -135,6 +135,13 @@ TimeZoneTest::TestGenericAPI() | |
| 188 infoln("WARNING: t_timezone may be incorrect. It is not a multiple of 1
5min.", tzoffset); | |
| 189 } | |
| 190 | |
| 191 + TimeZone* hostZone = TimeZone::detectHostTimeZone(); | |
| 192 + /* Host time zone's offset should match the offset returned by uprv_timezon
e() */ | |
| 193 + if (hostZone->getRawOffset() != tzoffset * (-1000)) { | |
| 194 + errln("FAIL: detectHostTimeZone()'s raw offset != host timezone's offse
t"); | |
| 195 + } | |
| 196 + delete hostZone; | |
| 197 + | |
| 198 UErrorCode status = U_ZERO_ERROR; | |
| 199 const char* tzver = TimeZone::getTZDataVersion(status); | |
| 200 if (U_FAILURE(status)) { | |
| OLD | NEW |