Adjust tzset() implementation to better follow the POSIX specs and
make some more perl tests happy. * no longer expect a ICU timezone ID in the TZ environment variable, but only expect this format if the TZ-value is starting with ':' * accept "standard" TZ-values like "EST5" (of which only "EST" is relevant to us) - if such a value is specified, we hardcode the timezone name to the given value, no matter how ICU calls it * adjust tests accordingly git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39415 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -45,7 +45,7 @@ public:
|
|||||||
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
||||||
size_t& outSize);
|
size_t& outSize);
|
||||||
|
|
||||||
virtual status_t TZSet(const char* timeZoneID);
|
virtual status_t TZSet(const char* timeZoneID, const char* tz);
|
||||||
virtual status_t Localtime(const time_t* inTime,
|
virtual status_t Localtime(const time_t* inTime,
|
||||||
struct tm* tmOut);
|
struct tm* tmOut);
|
||||||
virtual status_t Gmtime(const time_t* inTime, struct tm* tmOut);
|
virtual status_t Gmtime(const time_t* inTime, struct tm* tmOut);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public:
|
|||||||
virtual void Initialize(
|
virtual void Initialize(
|
||||||
TimeConversionDataBridge* dataBridge);
|
TimeConversionDataBridge* dataBridge);
|
||||||
|
|
||||||
status_t TZSet(const char* timeZoneID);
|
status_t TZSet(const char* timeZoneID, const char* tz);
|
||||||
|
|
||||||
status_t Localtime(const time_t* inTime,
|
status_t Localtime(const time_t* inTime,
|
||||||
struct tm* tmOut);
|
struct tm* tmOut);
|
||||||
|
|||||||
@@ -127,7 +127,8 @@ public:
|
|||||||
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
||||||
size_t& outSize) = 0;
|
size_t& outSize) = 0;
|
||||||
|
|
||||||
virtual status_t TZSet(const char* timeZoneID) = 0;
|
virtual status_t TZSet(const char* timeZoneID,
|
||||||
|
const char* tz) = 0;
|
||||||
virtual status_t Localtime(const time_t* inTime,
|
virtual status_t Localtime(const time_t* inTime,
|
||||||
struct tm* tmOut) = 0;
|
struct tm* tmOut) = 0;
|
||||||
virtual status_t Gmtime(const time_t* inTime,
|
virtual status_t Gmtime(const time_t* inTime,
|
||||||
|
|||||||
@@ -245,11 +245,11 @@ ICULocaleBackend::Strxfrm(char* out, const char* in, size_t size,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ICULocaleBackend::TZSet(const char* timeZoneID)
|
ICULocaleBackend::TZSet(const char* timeZoneID, const char* tz)
|
||||||
{
|
{
|
||||||
ErrnoMaintainer errnoMaintainer;
|
ErrnoMaintainer errnoMaintainer;
|
||||||
|
|
||||||
return fTimeConversion.TZSet(timeZoneID);
|
return fTimeConversion.TZSet(timeZoneID, tz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,13 +39,41 @@ ICUTimeConversion::Initialize(TimeConversionDataBridge* dataBridge)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ICUTimeConversion::TZSet(const char* timeZoneID)
|
ICUTimeConversion::TZSet(const char* timeZoneID, const char* tz)
|
||||||
{
|
{
|
||||||
// nothing to do if the given name matches any name of the current timezone
|
// The given TZ environment variable's content overrides the default
|
||||||
|
// system timezone.
|
||||||
|
if (tz != NULL) {
|
||||||
|
// If the value given in the TZ env-var starts with a colon, that
|
||||||
|
// value is implementation specific, we expect a full timezone ID.
|
||||||
|
if (*tz == ':') {
|
||||||
|
// nothing to do if the given name matches the current timezone
|
||||||
|
if (strcasecmp(fTimeZoneID, tz + 1) == 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
strlcpy(fTimeZoneID, tz + 1, sizeof(fTimeZoneID));
|
||||||
|
} else {
|
||||||
|
// We ignore anything following the timezone name, as those values
|
||||||
|
// are determined by the corresponding ICU-timezone (and glibc's
|
||||||
|
// tzset() implementation seems to do the same).
|
||||||
|
const char* tzNameEnd = tz;
|
||||||
|
while(isalpha(*tzNameEnd))
|
||||||
|
++tzNameEnd;
|
||||||
|
|
||||||
|
strlcpy(fTimeZoneID, tz,
|
||||||
|
min_c((uint32)(1 + tzNameEnd - tz), sizeof(fTimeZoneID)));
|
||||||
|
|
||||||
|
// nothing to do if the given name matches the current timezone
|
||||||
|
if (strcasecmp(fTimeZoneID, fDataBridge->addrOfTZName[0]) == 0)
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// nothing to do if the given name matches the current timezone
|
||||||
if (strcasecmp(fTimeZoneID, timeZoneID) == 0)
|
if (strcasecmp(fTimeZoneID, timeZoneID) == 0)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
strlcpy(fTimeZoneID, timeZoneID, sizeof(fTimeZoneID));
|
strlcpy(fTimeZoneID, timeZoneID, sizeof(fTimeZoneID));
|
||||||
|
}
|
||||||
|
|
||||||
ObjectDeleter<TimeZone> icuTimeZone = TimeZone::createTimeZone(fTimeZoneID);
|
ObjectDeleter<TimeZone> icuTimeZone = TimeZone::createTimeZone(fTimeZoneID);
|
||||||
if (icuTimeZone.Get() == NULL)
|
if (icuTimeZone.Get() == NULL)
|
||||||
@@ -71,6 +99,9 @@ ICUTimeConversion::TZSet(const char* timeZoneID)
|
|||||||
*fDataBridge->addrOfDaylight = icuTimeZone->useDaylightTime();
|
*fDataBridge->addrOfDaylight = icuTimeZone->useDaylightTime();
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
if (tz != NULL && *tz != ':' && i == 0) {
|
||||||
|
strcpy(fDataBridge->addrOfTZName[0], fTimeZoneID);
|
||||||
|
} else {
|
||||||
UnicodeString icuString;
|
UnicodeString icuString;
|
||||||
icuTimeZone->getDisplayName(i == 1, TimeZone::SHORT_COMMONLY_USED,
|
icuTimeZone->getDisplayName(i == 1, TimeZone::SHORT_COMMONLY_USED,
|
||||||
fTimeData.ICULocale(), icuString);
|
fTimeData.ICULocale(), icuString);
|
||||||
@@ -82,6 +113,7 @@ ICUTimeConversion::TZSet(const char* timeZoneID)
|
|||||||
if (strcmp(fDataBridge->addrOfTZName[i], "GMT+00:00") == 0)
|
if (strcmp(fDataBridge->addrOfTZName[i], "GMT+00:00") == 0)
|
||||||
fDataBridge->addrOfTZName[i][3] = '\0';
|
fDataBridge->addrOfTZName[i][3] = '\0';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,15 +39,9 @@ tzset(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
char timeZoneID[B_FILE_NAME_LENGTH] = { "GMT" };
|
char timeZoneID[B_FILE_NAME_LENGTH] = { "GMT" };
|
||||||
|
|
||||||
const char* tz = getenv("TZ");
|
|
||||||
if (tz != NULL)
|
|
||||||
strlcpy(timeZoneID, tz, sizeof(timeZoneID));
|
|
||||||
else
|
|
||||||
_kern_get_timezone(NULL, timeZoneID, sizeof(timeZoneID));
|
_kern_get_timezone(NULL, timeZoneID, sizeof(timeZoneID));
|
||||||
|
|
||||||
if (gLocaleBackend != NULL)
|
gLocaleBackend->TZSet(timeZoneID, getenv("TZ"));
|
||||||
gLocaleBackend->TZSet(timeZoneID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1819,30 +1819,42 @@ test_timeconversions()
|
|||||||
gtm.tm_wday = -1;
|
gtm.tm_wday = -1;
|
||||||
gtm.tm_yday = -1;
|
gtm.tm_yday = -1;
|
||||||
test_mktime("GMT", gtm, testTime, 6, 197);
|
test_mktime("GMT", gtm, testTime, 6, 197);
|
||||||
|
|
||||||
tm btm = {
|
tm btm = {
|
||||||
9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST"
|
9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST"
|
||||||
};
|
};
|
||||||
test_localtime("Europe/Berlin", testTime, btm);
|
test_localtime(":Europe/Berlin", testTime, btm);
|
||||||
test_gmtime("Europe/Berlin", testTime, gtm);
|
test_gmtime(":Europe/Berlin", testTime, gtm);
|
||||||
btm.tm_wday = -1;
|
btm.tm_wday = -1;
|
||||||
btm.tm_yday = -1;
|
btm.tm_yday = -1;
|
||||||
test_mktime("Europe/Berlin", btm, testTime, 6, 197);
|
test_mktime(":Europe/Berlin", btm, testTime, 6, 197);
|
||||||
|
|
||||||
|
tm ctm = {
|
||||||
|
9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST"
|
||||||
|
};
|
||||||
|
test_localtime("CET", testTime, ctm);
|
||||||
|
test_gmtime("CET", testTime, gtm);
|
||||||
|
ctm.tm_wday = -1;
|
||||||
|
ctm.tm_yday = -1;
|
||||||
|
test_mktime("CET", ctm, testTime, 6, 197);
|
||||||
|
|
||||||
tm latm = {
|
tm latm = {
|
||||||
9, 26, 11, 17, 6, 110, 6, 197, 1, -7 * 3600, (char*)"PDT"
|
9, 26, 11, 17, 6, 110, 6, 197, 1, -7 * 3600, (char*)"PDT"
|
||||||
};
|
};
|
||||||
test_localtime("America/Los_Angeles", testTime, latm);
|
test_localtime(":America/Los_Angeles", testTime, latm);
|
||||||
test_gmtime("America/Los_Angeles", testTime, gtm);
|
test_gmtime(":America/Los_Angeles", testTime, gtm);
|
||||||
latm.tm_wday = -1;
|
latm.tm_wday = -1;
|
||||||
latm.tm_yday = -1;
|
latm.tm_yday = -1;
|
||||||
test_mktime("America/Los_Angeles", latm, testTime, 6, 197);
|
test_mktime(":America/Los_Angeles", latm, testTime, 6, 197);
|
||||||
|
|
||||||
tm ttm = {
|
tm ttm = {
|
||||||
9, 26, 3, 18, 6, 110, 0, 198, 0, 9 * 3600, (char*)"JST"
|
9, 26, 3, 18, 6, 110, 0, 198, 0, 9 * 3600, (char*)"JST"
|
||||||
};
|
};
|
||||||
test_localtime("Asia/Tokyo", testTime, ttm);
|
test_localtime(":Asia/Tokyo", testTime, ttm);
|
||||||
test_gmtime("Asia/Tokyo", testTime, gtm);
|
test_gmtime(":Asia/Tokyo", testTime, gtm);
|
||||||
ttm.tm_wday = -1;
|
ttm.tm_wday = -1;
|
||||||
ttm.tm_yday = -1;
|
ttm.tm_yday = -1;
|
||||||
test_mktime("Asia/Tokyo", ttm, testTime, 0, 198);
|
test_mktime(":Asia/Tokyo", ttm, testTime, 0, 198);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1855,30 +1867,42 @@ test_timeconversions()
|
|||||||
gtm.tm_wday = -1;
|
gtm.tm_wday = -1;
|
||||||
gtm.tm_yday = -1;
|
gtm.tm_yday = -1;
|
||||||
test_mktime("GMT", gtm, testTime, 2, 67);
|
test_mktime("GMT", gtm, testTime, 2, 67);
|
||||||
|
|
||||||
tm btm = {
|
tm btm = {
|
||||||
9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET"
|
9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET"
|
||||||
};
|
};
|
||||||
test_localtime("Europe/Berlin", testTime, btm);
|
test_localtime(":Europe/Berlin", testTime, btm);
|
||||||
test_gmtime("Europe/Berlin", testTime, gtm);
|
test_gmtime(":Europe/Berlin", testTime, gtm);
|
||||||
btm.tm_wday = -1;
|
btm.tm_wday = -1;
|
||||||
btm.tm_yday = -1;
|
btm.tm_yday = -1;
|
||||||
test_mktime("Europe/Berlin", btm, testTime, 2, 67);
|
test_mktime(":Europe/Berlin", btm, testTime, 2, 67);
|
||||||
|
|
||||||
|
tm ctm = {
|
||||||
|
9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET"
|
||||||
|
};
|
||||||
|
test_localtime("CET", testTime, ctm);
|
||||||
|
test_gmtime("CET", testTime, gtm);
|
||||||
|
ctm.tm_wday = -1;
|
||||||
|
ctm.tm_yday = -1;
|
||||||
|
test_mktime("CET", ctm, testTime, 2, 67);
|
||||||
|
|
||||||
tm latm = {
|
tm latm = {
|
||||||
9, 26, 10, 9, 2, 110, 2, 67, 0, -8 * 3600, (char*)"PST"
|
9, 26, 10, 9, 2, 110, 2, 67, 0, -8 * 3600, (char*)"PST"
|
||||||
};
|
};
|
||||||
test_localtime("America/Los_Angeles", testTime, latm);
|
test_localtime(":America/Los_Angeles", testTime, latm);
|
||||||
test_gmtime("America/Los_Angeles", testTime, gtm);
|
test_gmtime(":America/Los_Angeles", testTime, gtm);
|
||||||
latm.tm_wday = -1;
|
latm.tm_wday = -1;
|
||||||
latm.tm_yday = -1;
|
latm.tm_yday = -1;
|
||||||
test_mktime("America/Los_Angeles", latm, testTime, 2, 67);
|
test_mktime(":America/Los_Angeles", latm, testTime, 2, 67);
|
||||||
|
|
||||||
tm ttm = {
|
tm ttm = {
|
||||||
9, 26, 3, 10, 2, 110, 3, 68, 0, 9 * 3600, (char*)"JST"
|
9, 26, 3, 10, 2, 110, 3, 68, 0, 9 * 3600, (char*)"JST"
|
||||||
};
|
};
|
||||||
test_localtime("Asia/Tokyo", testTime, ttm);
|
test_localtime(":Asia/Tokyo", testTime, ttm);
|
||||||
test_gmtime("Asia/Tokyo", testTime, gtm);
|
test_gmtime(":Asia/Tokyo", testTime, gtm);
|
||||||
ttm.tm_wday = -1;
|
ttm.tm_wday = -1;
|
||||||
ttm.tm_yday = -1;
|
ttm.tm_yday = -1;
|
||||||
test_mktime("Asia/Tokyo", ttm, testTime, 3, 68);
|
test_mktime(":Asia/Tokyo", ttm, testTime, 3, 68);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1891,30 +1915,42 @@ test_timeconversions()
|
|||||||
gtm.tm_wday = -1;
|
gtm.tm_wday = -1;
|
||||||
gtm.tm_yday = -1;
|
gtm.tm_yday = -1;
|
||||||
test_mktime("GMT", gtm, testTime, 4, 0);
|
test_mktime("GMT", gtm, testTime, 4, 0);
|
||||||
|
|
||||||
tm btm = {
|
tm btm = {
|
||||||
0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET"
|
0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET"
|
||||||
};
|
};
|
||||||
test_localtime("Europe/Berlin", testTime, btm);
|
test_localtime(":Europe/Berlin", testTime, btm);
|
||||||
test_gmtime("Europe/Berlin", testTime, gtm);
|
test_gmtime(":Europe/Berlin", testTime, gtm);
|
||||||
btm.tm_wday = -1;
|
btm.tm_wday = -1;
|
||||||
btm.tm_yday = -1;
|
btm.tm_yday = -1;
|
||||||
test_mktime("Europe/Berlin", btm, testTime, 4, 0);
|
test_mktime(":Europe/Berlin", btm, testTime, 4, 0);
|
||||||
|
|
||||||
|
tm ctm = {
|
||||||
|
0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET"
|
||||||
|
};
|
||||||
|
test_localtime("CET", testTime, ctm);
|
||||||
|
test_gmtime("CET", testTime, gtm);
|
||||||
|
ctm.tm_wday = -1;
|
||||||
|
ctm.tm_yday = -1;
|
||||||
|
test_mktime("CET", ctm, testTime, 4, 0);
|
||||||
|
|
||||||
tm latm = {
|
tm latm = {
|
||||||
0, 0, 16, 31, 11, 69, 3, 364, 0, -8 * 3600, (char*)"PST"
|
0, 0, 16, 31, 11, 69, 3, 364, 0, -8 * 3600, (char*)"PST"
|
||||||
};
|
};
|
||||||
test_localtime("America/Los_Angeles", testTime, latm);
|
test_localtime(":America/Los_Angeles", testTime, latm);
|
||||||
test_gmtime("America/Los_Angeles", testTime, gtm);
|
test_gmtime(":America/Los_Angeles", testTime, gtm);
|
||||||
latm.tm_wday = -1;
|
latm.tm_wday = -1;
|
||||||
latm.tm_yday = -1;
|
latm.tm_yday = -1;
|
||||||
test_mktime("America/Los_Angeles", latm, testTime, 3, 364);
|
test_mktime(":America/Los_Angeles", latm, testTime, 3, 364);
|
||||||
|
|
||||||
tm ttm = {
|
tm ttm = {
|
||||||
0, 0, 9, 1, 0, 70, 4, 0, 0, 9 * 3600, (char*)"JST"
|
0, 0, 9, 1, 0, 70, 4, 0, 0, 9 * 3600, (char*)"JST"
|
||||||
};
|
};
|
||||||
test_localtime("Asia/Tokyo", testTime, ttm);
|
test_localtime(":Asia/Tokyo", testTime, ttm);
|
||||||
test_gmtime("Asia/Tokyo", testTime, gtm);
|
test_gmtime(":Asia/Tokyo", testTime, gtm);
|
||||||
ttm.tm_wday = -1;
|
ttm.tm_wday = -1;
|
||||||
ttm.tm_yday = -1;
|
ttm.tm_yday = -1;
|
||||||
test_mktime("Asia/Tokyo", ttm, testTime, 4, 0);
|
test_mktime(":Asia/Tokyo", ttm, testTime, 4, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user