[haiku-commits] r40788 - in haiku/trunk: headers/private/libroot/locale src/system/libroot/add-ons/icu src/tests/system/libroot/posix

  • From: zooey@xxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 3 Mar 2011 01:34:52 +0100 (CET)

Author: zooey
Date: 2011-03-03 01:34:51 +0100 (Thu, 03 Mar 2011)
New Revision: 40788
Changeset: http://dev.haiku-os.org/changeset/40788

Modified:
   haiku/trunk/headers/private/libroot/locale/ICUTimeConversion.h
   haiku/trunk/src/system/libroot/add-ons/icu/ICUTimeConversion.cpp
   haiku/trunk/src/tests/system/libroot/posix/locale_test.cpp
Log:
* fix support for influencing tzset() via TZ environment variable
  (now at least <std> and <offset> are supported properly)
* instead of creating a TimeZone object whenever needed, we now
  create it in tzset() and keep it around
* add tests for TZ to locale_test

Modified: haiku/trunk/headers/private/libroot/locale/ICUTimeConversion.h
===================================================================
--- haiku/trunk/headers/private/libroot/locale/ICUTimeConversion.h      
2011-03-02 18:58:14 UTC (rev 40787)
+++ haiku/trunk/headers/private/libroot/locale/ICUTimeConversion.h      
2011-03-03 00:34:51 UTC (rev 40788)
@@ -42,6 +42,7 @@
 
                        TimeConversionDataBridge*       fDataBridge;
 
+                       TimeZone*                       fTimeZone;
                        char                            
fTimeZoneID[B_FILE_NAME_LENGTH];
 };
 

Modified: haiku/trunk/src/system/libroot/add-ons/icu/ICUTimeConversion.cpp
===================================================================
--- haiku/trunk/src/system/libroot/add-ons/icu/ICUTimeConversion.cpp    
2011-03-02 18:58:14 UTC (rev 40787)
+++ haiku/trunk/src/system/libroot/add-ons/icu/ICUTimeConversion.cpp    
2011-03-03 00:34:51 UTC (rev 40788)
@@ -21,7 +21,8 @@
 ICUTimeConversion::ICUTimeConversion(const ICUTimeData& timeData)
        :
        fTimeData(timeData),
-       fDataBridge(NULL)
+       fDataBridge(NULL),
+       fTimeZone(NULL)
 {
        fTimeZoneID[0] = '\0';
 }
@@ -29,6 +30,7 @@
 
 ICUTimeConversion::~ICUTimeConversion()
 {
+       delete fTimeZone;
 }
 
 
@@ -42,6 +44,8 @@
 status_t
 ICUTimeConversion::TZSet(const char* timeZoneID, const char* tz)
 {
+       bool offsetHasBeenSet = false;
+
        // The given TZ environment variable's content overrides the default
        // system timezone.
        if (tz != NULL) {
@@ -54,19 +58,31 @@
 
                        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).
+                       // note timezone name
+                       strlcpy(fTimeZoneID, tz, sizeof(fTimeZoneID));
+
+                       // nothing to do if the given name matches the current 
timezone
+                       if (strcasecmp(fTimeZoneID, 
fDataBridge->addrOfTZName[0]) == 0)
+                               return B_OK;
+
+                       // parse TZ variable (only <std> and <offset> supported)
                        const char* tzNameEnd = tz;
                        while(isalpha(*tzNameEnd))
                                ++tzNameEnd;
+                       if (*tzNameEnd == '-' || *tzNameEnd == '+') {
+                               int hours = 0;
+                               int minutes = 0;
+                               int seconds = 0;
+                               sscanf(tzNameEnd + 1, "%2d:%2d:%2d", &hours, 
&minutes,
+                                       &seconds);
+                               hours = min_c(24, max_c(0, hours));
+                               minutes = min_c(59, max_c(0, minutes));
+                               seconds = min_c(59, max_c(0, seconds));
 
-                       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;
+                               *fDataBridge->addrOfTimezone = (*tzNameEnd == 
'-' ? -1 : 1)
+                                       * (hours * 3600 + minutes * 60 + 
seconds);
+                               offsetHasBeenSet = true;
+                       }
                }
        } else {
                // nothing to do if the given name matches the current timezone
@@ -76,35 +92,39 @@
                strlcpy(fTimeZoneID, timeZoneID, sizeof(fTimeZoneID));
        }
 
-       ObjectDeleter<TimeZone> icuTimeZone = 
TimeZone::createTimeZone(fTimeZoneID);
-       if (icuTimeZone.Get() == NULL)
+       delete fTimeZone;
+       fTimeZone = TimeZone::createTimeZone(fTimeZoneID);
+       if (fTimeZone == NULL)
                return B_NO_MEMORY;
 
-       int32_t rawOffset;
-       int32_t dstOffset;
-       UDate nowMillis = 1000 * (UDate)time(NULL);
-       UErrorCode icuStatus = U_ZERO_ERROR;
-       icuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, 
icuStatus);
-       if (!U_SUCCESS(icuStatus)) {
-               *fDataBridge->addrOfTimezone = 0;
-               *fDataBridge->addrOfDaylight = false;
-               strcpy(fDataBridge->addrOfTZName[0], "GMT");
-               strcpy(fDataBridge->addrOfTZName[1], "GMT");
+       if (offsetHasBeenSet) {
+               fTimeZone->setRawOffset(*fDataBridge->addrOfTimezone * -1 * 
1000);
+       } else {
+               int32_t rawOffset;
+               int32_t dstOffset;
+               UDate nowMillis = 1000 * (UDate)time(NULL);
+               UErrorCode icuStatus = U_ZERO_ERROR;
+               fTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, 
icuStatus);
+               if (!U_SUCCESS(icuStatus)) {
+                       *fDataBridge->addrOfTimezone = 0;
+                       *fDataBridge->addrOfDaylight = false;
+                       strcpy(fDataBridge->addrOfTZName[0], "GMT");
+                       strcpy(fDataBridge->addrOfTZName[1], "GMT");
 
-               return B_ERROR;
+                       return B_ERROR;
+               }
+               *fDataBridge->addrOfTimezone = -1 * (rawOffset + dstOffset) / 
1000;
+                       // we want seconds, not the ms that ICU gives us
        }
 
-       *fDataBridge->addrOfTimezone = -1 * (rawOffset + dstOffset) / 1000;
-               // we want seconds, not the ms that ICU gives us
+       *fDataBridge->addrOfDaylight = fTimeZone->useDaylightTime();
 
-       *fDataBridge->addrOfDaylight = icuTimeZone->useDaylightTime();
-
        for (int i = 0; i < 2; ++i) {
                if (tz != NULL && *tz != ':' && i == 0) {
                        strcpy(fDataBridge->addrOfTZName[0], fTimeZoneID);
                } else {
                        UnicodeString icuString;
-                       icuTimeZone->getDisplayName(i == 1, 
TimeZone::SHORT_COMMONLY_USED,
+                       fTimeZone->getDisplayName(i == 1, 
TimeZone::SHORT_COMMONLY_USED,
                                fTimeData.ICULocale(), icuString);
                        CheckedArrayByteSink 
byteSink(fDataBridge->addrOfTZName[i],
                                sizeof(fTimeZoneID));
@@ -123,12 +143,11 @@
 status_t
 ICUTimeConversion::Localtime(const time_t* inTime, struct tm* tmOut)
 {
-       ObjectDeleter<TimeZone> icuTimeZone = 
TimeZone::createTimeZone(fTimeZoneID);
-       if (icuTimeZone.Get() == NULL)
-               return B_NO_MEMORY;
+       if (fTimeZone == NULL)
+               return B_NO_INIT;
 
        tmOut->tm_zone = fTimeZoneID;
-       return _FillTmValues(icuTimeZone.Get(), inTime, tmOut);
+       return _FillTmValues(fTimeZone, inTime, tmOut);
 }
 
 
@@ -145,12 +164,11 @@
 status_t
 ICUTimeConversion::Mktime(struct tm* inOutTm, time_t& timeOut)
 {
-       ObjectDeleter<TimeZone> icuTimeZone = 
TimeZone::createTimeZone(fTimeZoneID);
-       if (icuTimeZone.Get() == NULL)
-               return B_NO_MEMORY;
+       if (fTimeZone == NULL)
+               return B_NO_INIT;
 
        UErrorCode icuStatus = U_ZERO_ERROR;
-       GregorianCalendar calendar(*icuTimeZone.Get(), fTimeData.ICULocale(),
+       GregorianCalendar calendar(*fTimeZone, fTimeData.ICULocale(),
                icuStatus);
        if (!U_SUCCESS(icuStatus))
                return B_ERROR;
@@ -164,7 +182,7 @@
                return B_ERROR;
        timeOut = (time_t)((int64_t)timeInMillis / 1000);
 
-       return _FillTmValues(icuTimeZone.Get(), &timeOut, inOutTm);
+       return _FillTmValues(fTimeZone, &timeOut, inOutTm);
 }
 
 

Modified: haiku/trunk/src/tests/system/libroot/posix/locale_test.cpp
===================================================================
--- haiku/trunk/src/tests/system/libroot/posix/locale_test.cpp  2011-03-02 
18:58:14 UTC (rev 40787)
+++ haiku/trunk/src/tests/system/libroot/posix/locale_test.cpp  2011-03-03 
00:34:51 UTC (rev 40788)
@@ -1820,6 +1820,24 @@
                gtm.tm_yday = -1;
                test_mktime("GMT", gtm, testTime, 6, 197);
 
+               tm gtmplus2 = {
+                       9, 26, 16, 17, 6, 110, 6, 197, 0, -2 * 3600, 
(char*)"GMT+2"
+               };
+               test_localtime("GMT+2", testTime, gtmplus2);
+               test_gmtime("GMT+2", testTime, gtm);
+               gtmplus2.tm_wday = -1;
+               gtmplus2.tm_yday = -1;
+               test_mktime("GMT+2", gtmplus2, testTime, 6, 197);
+
+               tm gtmminus2 = {
+                       9, 26, 20, 17, 6, 110, 6, 197, 0, 2 * 3600, 
(char*)"GMT-2"
+               };
+               test_localtime("GMT-2", testTime, gtmminus2);
+               test_gmtime("GMT-2", testTime, gtm);
+               gtmminus2.tm_wday = -1;
+               gtmminus2.tm_yday = -1;
+               test_mktime("GMT-2", gtmminus2, testTime, 6, 197);
+
                tm btm = {
                        9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, 
(char*)"CEST"
                };


Other related posts:

  • » [haiku-commits] r40788 - in haiku/trunk: headers/private/libroot/locale src/system/libroot/add-ons/icu src/tests/system/libroot/posix - zooey