static UMTX LOCK;
static UMTX TZSET_LOCK;
static icu::TimeZone* DEFAULT_ZONE = NULL;
-static icu::TimeZone* _GMT = NULL; // cf. TimeZone::GMT
+static icu::TimeZone* _GMT = NULL;
+static icu::TimeZone* _UNKNOWN_ZONE = NULL;
static char TZDATA_VERSION[16];
static UBool TZDataVersionInitialized = FALSE;
delete _GMT;
_GMT = NULL;
+ delete _UNKNOWN_ZONE;
+ _UNKNOWN_ZONE = NULL;
+
uprv_memset(TZDATA_VERSION, 0, sizeof(TZDATA_VERSION));
TZDataVersionInitialized = FALSE;
// -------------------------------------
-const TimeZone* U_EXPORT2
-TimeZone::getGMT(void)
-{
+namespace {
+
+void
+ensureStaticTimeZones() {
UBool needsInit;
UMTX_CHECK(&LOCK, (_GMT == NULL), needsInit); /* This is here to prevent race conditions. */
// Initialize _GMT independently of other static data; it should
// be valid even if we can't load the time zone UDataMemory.
if (needsInit) {
+ SimpleTimeZone *tmpUnknown =
+ new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
SimpleTimeZone *tmpGMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
umtx_lock(&LOCK);
+ if (_UNKNOWN_ZONE == 0) {
+ _UNKNOWN_ZONE = tmpUnknown;
+ tmpUnknown = NULL;
+ }
if (_GMT == 0) {
_GMT = tmpGMT;
tmpGMT = NULL;
}
umtx_unlock(&LOCK);
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
+ delete tmpUnknown;
delete tmpGMT;
}
+}
+
+} // anonymous namespace
+
+const TimeZone& U_EXPORT2
+TimeZone::getUnknown()
+{
+ ensureStaticTimeZones();
+ return *_UNKNOWN_ZONE;
+}
+
+const TimeZone* U_EXPORT2
+TimeZone::getGMT(void)
+{
+ ensureStaticTimeZones();
return _GMT;
}
}
if (result == 0) {
U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
- result = new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
+ result = getUnknown().clone();
}
return result;
}
virtual ~TimeZone();
/**
- * The GMT time zone has a raw offset of zero and does not use daylight
+ * Returns the "unknown" time zone.
+ * It behaves like the GMT/UTC time zone but has the
+ * <code>UCAL_UNKNOWN_ZONE_ID</code> = "Etc/Unknown".
+ * createTimeZone() returns a mutable clone of this time zone if the input ID is not recognized.
+ *
+ * @return the "unknown" time zone.
+ * @see UCAL_UNKNOWN_ZONE_ID
+ * @see createTimeZone
+ * @see getGMT
+ * @draft ICU 49
+ */
+ static const TimeZone& U_EXPORT2 getUnknown();
+
+ /**
+ * The GMT (=UTC) time zone has a raw offset of zero and does not use daylight
* savings time. This is a commonly used time zone.
*
* <p>Note: For backward compatibility reason, the ID used by the time
* zone returned by this method is "GMT", although the ICU's canonical
* ID for the GMT time zone is "Etc/GMT".
*
- * @return the GMT time zone.
+ * @return the GMT/UTC time zone.
+ * @see getUnknown
* @stable ICU 2.0
*/
static const TimeZone* U_EXPORT2 getGMT(void);
* Creates a <code>TimeZone</code> for the given ID.
* @param ID the ID for a <code>TimeZone</code>, such as "America/Los_Angeles",
* or a custom ID such as "GMT-8:00".
- * @return the specified <code>TimeZone</code>, or the GMT zone with ID
- * <code>UCAL_UNKNOWN_ZONE_ID</code> ("Etc/Unknown") if the given ID cannot be understood.
- * Return result guaranteed to be non-null. If you require that the specific zone asked
- * for be returned, check the ID of the return result.
+ * @return the specified <code>TimeZone</code>, or a mutable clone of getUnknown()
+ * if the given ID cannot be understood.
+ * The return result is guaranteed to be non-NULL.
+ * If you require that the specific zone asked for be returned,
+ * compare the result with getUnknown() or check the ID of the return result.
* @stable ICU 2.0
*/
static TimeZone* U_EXPORT2 createTimeZone(const UnicodeString& ID);
void TimeZoneTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
{
- if (exec) logln("TestSuite TestTimeZone");
- switch (index) {
- CASE(0, TestPRTOffset);
- CASE(1, TestVariousAPI518);
- CASE(2, TestGetAvailableIDs913);
- CASE(3, TestGenericAPI);
- CASE(4, TestRuleAPI);
- CASE(5, TestShortZoneIDs);
- CASE(6, TestCustomParse);
- CASE(7, TestDisplayName);
- CASE(8, TestDSTSavings);
- CASE(9, TestAlternateRules);
- CASE(10,TestCountries);
- CASE(11,TestHistorical);
- CASE(12,TestEquivalentIDs);
- CASE(13, TestAliasedNames);
- CASE(14, TestFractionalDST);
- CASE(15, TestFebruary);
- CASE(16, TestCanonicalID);
- CASE(17, TestDisplayNamesMeta);
- CASE(18, TestGetRegion);
- CASE(19, TestGetAvailableIDsNew);
- default: name = ""; break;
- }
+ if (exec) {
+ logln("TestSuite TestTimeZone");
+ }
+ TESTCASE_AUTO_BEGIN;
+ TESTCASE_AUTO(TestPRTOffset);
+ TESTCASE_AUTO(TestVariousAPI518);
+ TESTCASE_AUTO(TestGetAvailableIDs913);
+ TESTCASE_AUTO(TestGenericAPI);
+ TESTCASE_AUTO(TestRuleAPI);
+ TESTCASE_AUTO(TestShortZoneIDs);
+ TESTCASE_AUTO(TestCustomParse);
+ TESTCASE_AUTO(TestDisplayName);
+ TESTCASE_AUTO(TestDSTSavings);
+ TESTCASE_AUTO(TestAlternateRules);
+ TESTCASE_AUTO(TestCountries);
+ TESTCASE_AUTO(TestHistorical);
+ TESTCASE_AUTO(TestEquivalentIDs);
+ TESTCASE_AUTO(TestAliasedNames);
+ TESTCASE_AUTO(TestFractionalDST);
+ TESTCASE_AUTO(TestFebruary);
+ TESTCASE_AUTO(TestCanonicalID);
+ TESTCASE_AUTO(TestDisplayNamesMeta);
+ TESTCASE_AUTO(TestGetRegion);
+ TESTCASE_AUTO(TestGetAvailableIDsNew);
+ TESTCASE_AUTO(TestGetUnknown);
+ TESTCASE_AUTO_END;
}
const int32_t TimeZoneTest::millisPerHour = 3600000;
}
}
}
+
+void TimeZoneTest::TestGetUnknown() {
+ const TimeZone &unknown = TimeZone::getUnknown();
+ UnicodeString expectedID = UNICODE_STRING_SIMPLE("Etc/Unknown");
+ UnicodeString id;
+ assertEquals("getUnknown() wrong ID", expectedID, unknown.getID(id));
+ assertTrue("getUnknown() wrong offset", 0 == unknown.getRawOffset());
+ assertFalse("getUnknown() uses DST", unknown.useDaylightTime());
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */
virtual void TestDisplayNamesMeta();
void TestGetRegion(void);
+ void TestGetUnknown();
static const UDate INTERVAL;