]> granicus.if.org Git - php/commitdiff
- MF51: Windows Timezone guessing code
authorDerick Rethans <derick@php.net>
Wed, 5 Oct 2005 18:38:30 +0000 (18:38 +0000)
committerDerick Rethans <derick@php.net>
Wed, 5 Oct 2005 18:38:30 +0000 (18:38 +0000)
ext/date/php_date.c
ext/date/php_date.h

index b1f2aea9278d42032b09653085bc4cf0168e94f2..20865106aac4b8679dab23b4298e5d98e0dc5139 100644 (file)
@@ -187,6 +187,14 @@ static void php_date_init_globals(zend_date_globals *date_globals)
 }
 /* }}} */
 
+
+static void _php_date_tzinfo_dtor(void *tzinfo)
+{
+       timelib_tzinfo **tzi = (timelib_tzinfo **)tzinfo;
+
+       timelib_tzinfo_dtor(*tzi);
+}
+
 /* {{{ PHP_RINIT_FUNCTION */
 PHP_RINIT_FUNCTION(date)
 {
@@ -194,6 +202,7 @@ PHP_RINIT_FUNCTION(date)
                efree(DATEG(timezone));
        }
        DATEG(timezone) = NULL;
+       zend_hash_init(&DATEG(tzcache), 4, NULL, _php_date_tzinfo_dtor, 0);
 
        return SUCCESS;
 }
@@ -206,6 +215,7 @@ PHP_RSHUTDOWN_FUNCTION(date)
                efree(DATEG(timezone));
        }
        DATEG(timezone) = NULL;
+       zend_hash_destroy(&DATEG(tzcache));
 
        return SUCCESS;
 }
@@ -269,6 +279,20 @@ PHP_MINFO_FUNCTION(date)
 }
 /* }}} */
 
+/* {{{ Timezone Cache functions */
+static timelib_tzinfo *php_date_parse_tzfile(char *tzname, timelib_tzdb *tzdb TSRMLS_DC)
+{
+       timelib_tzinfo *tzi, **ptzi;
+
+       if (zend_hash_find(&DATEG(tzcache), tzname, strlen(tzname) + 1, (void **) &ptzi) == SUCCESS) {
+               return *ptzi;
+       }
+
+       tzi = timelib_parse_tzfile(tzname, tzdb);
+       zend_hash_add(&DATEG(tzcache), tzname, strlen(tzname) + 1, (void *) &tzi, sizeof(timelib_tzinfo*), NULL);
+       return tzi;
+}
+/* }}} */
 
 /* {{{ Helper functions */
 static char* guess_timezone(TSRMLS_D)
@@ -281,7 +305,7 @@ static char* guess_timezone(TSRMLS_D)
        }
        /* Check environment variable */
        env = getenv("TZ");
-       if (env && *env && strlen(env)) {
+       if (env && *env) {
                return env;
        }
        /* Check config setting for default timezone */
@@ -305,6 +329,37 @@ static char* guess_timezone(TSRMLS_D)
                php_error_docref(NULL TSRMLS_CC, E_STRICT, "It is not safe to rely on the systems timezone settings, please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. We use '%s' for '%s/%.1f/%s' instead.", tzid, ta->tm_zone, (float) (ta->tm_gmtoff / 3600), ta->tm_isdst ? "DST" : "no DST");
                return tzid;
        }
+#endif
+#ifdef PHP_WIN32
+       {
+               char *tzid;
+               TIME_ZONE_INFORMATION tzi;
+
+               switch (GetTimeZoneInformation(&tzi))
+               {
+                       case TIME_ZONE_ID_UNKNOWN:
+                               /* we have no clue what it is, return UTC */
+                               php_error_docref(NULL TSRMLS_CC, E_STRICT, "It is not safe to rely on the systems timezone settings, please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. We use 'UTC' instead.");
+                               break;
+
+                       case TIME_ZONE_ID_STANDARD:
+                               tzid = timelib_timezone_id_from_abbr("", (tzi.Bias + tzi.StandardBias) * -60, 0);
+                               if (! tzid) {
+                                       tzid = "UTC";
+                               }
+                               php_error_docref(NULL TSRMLS_CC, E_STRICT, "It is not safe to rely on the systems timezone settings, please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. We use '%s' for '%.1f/no DST' instead.", tzid, (float) ((tzi.Bias + tzi.StandardBias) / -60));
+                               break;
+
+                       case TIME_ZONE_ID_DAYLIGHT:
+                               tzid = timelib_timezone_id_from_abbr("", (tzi.Bias + tzi.DaylightBias) * -60, 1);
+                               if (! tzid) {
+                                       tzid = "UTC";
+                               }
+                               php_error_docref(NULL TSRMLS_CC, E_STRICT, "It is not safe to rely on the systems timezone settings, please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. We use '%s' for '%.1f/DST' instead.", tzid, (float) ((tzi.Bias + tzi.DaylightBias) / -60));
+                               break;
+
+               }
+       }
 #endif
        /* Fallback to UTC */
        return "UTC";
@@ -316,10 +371,10 @@ static timelib_tzinfo *get_timezone_info(TSRMLS_D)
        timelib_tzinfo *tzi;
        
        tz = guess_timezone(TSRMLS_C);
-       tzi = timelib_parse_tzfile(tz, DATE_TIMEZONEDB);
+       tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC);
        if (! tzi) {
                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Timezone setting (date.timezone) or TZ environment variable contains an unknown timezone.");
-               tzi = timelib_parse_tzfile("UTC", DATE_TIMEZONEDB);
+               tzi = php_date_parse_tzfile("UTC", DATE_TIMEZONEDB TSRMLS_CC);
 
                if (! tzi) {
                        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Timezone database is corrupt - this should *never* happen!");
@@ -600,11 +655,14 @@ static char *date_format(char *format, int format_len, int *return_len, timelib_
 
 static void php_date(INTERNAL_FUNCTION_PARAMETERS, int localtime)
 {
-       char *format;
-       int   format_len;
-       time_t  ts = time(NULL);
-       char           *string;
+       char   *format;
+       int     format_len;
+       time_t  ts;
+       char   *string;
 
+       if (ZEND_NUM_ARGS() == 1) {
+               ts = time(NULL);
+       }
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) {
                RETURN_FALSE;
        }
@@ -638,10 +696,6 @@ PHPAPI char *php_format_date(char *format, int format_len, time_t ts, int localt
 
        string = date_format(format, format_len, &return_len, t, localtime, 0 TSRMLS_CC);
        
-       if (localtime) {
-               timelib_tzinfo_dtor(tzi);
-       }
-       
        timelib_time_dtor(t);
        return string;
 }
@@ -723,7 +777,6 @@ PHP_FUNCTION(strtotime)
                now = timelib_time_ctor();
                timelib_unixtime2local(now, (timelib_sll) time(NULL), tzi);
        } else {
-               timelib_tzinfo_dtor(tzi);
                RETURN_FALSE;
        }
 
@@ -740,7 +793,6 @@ PHP_FUNCTION(strtotime)
                timelib_tzinfo_dtor(t->tz_info);
        }
 
-       timelib_tzinfo_dtor(tzi);
        timelib_time_dtor(now); 
        timelib_time_dtor(t);
 
@@ -834,9 +886,6 @@ PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
        ts = timelib_date_to_int(now, &error);
        ts += adjust_seconds;
        timelib_time_dtor(now);
-       if (!gmt) {
-               timelib_tzinfo_dtor(tzi);
-       }
 
        if (error) {
                RETURN_FALSE;
@@ -940,10 +989,6 @@ PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
 #endif
        }
 
-       if (!gmt) {
-               timelib_tzinfo_dtor(tzi);
-       }
-       
        buf = (char *) emalloc(buf_len);
        while ((real_len=strftime(buf, buf_len, format, &ta))==buf_len || real_len==0) {
                buf_len *= 2;
@@ -1033,7 +1078,6 @@ PHP_FUNCTION(localtime)
                add_next_index_long(return_value, ts->dst);
        }
 
-       timelib_tzinfo_dtor(tzi);
        timelib_time_dtor(ts);
 }
 /* }}} */
@@ -1068,7 +1112,6 @@ PHP_FUNCTION(getdate)
        add_assoc_string(return_value, "month", mon_full_names[ts->m - 1], 1);
        add_index_long(return_value, 0, timestamp);
 
-       timelib_tzinfo_dtor(tzi);
        timelib_time_dtor(ts);
 }
 /* }}} */
@@ -1120,8 +1163,6 @@ static void date_object_free_storage_timezone(void *object TSRMLS_DC)
 {
        php_timezone_obj *intern = (php_timezone_obj *)object;
 
-       timelib_tzinfo_dtor(intern->tz);
-       
        efree(object);
 }
 
@@ -1164,7 +1205,7 @@ PHP_FUNCTION(date_create)
        timelib_time   *now;
        timelib_tzinfo *tzi;
        char           *time_str;
-       int             time_str_len = 0;
+       int             time_str_len = 0, free_tzi = 0;;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO", &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
                RETURN_FALSE;
@@ -1179,8 +1220,10 @@ PHP_FUNCTION(date_create)
 
                tzobj = (php_timezone_obj *) zend_object_store_get_object(timezone_object TSRMLS_CC);
                tzi = timelib_tzinfo_clone(tzobj->tz);
+               free_tzi = 1;
        } else if (dateobj->time->tz_info) {
                tzi = timelib_tzinfo_clone(dateobj->time->tz_info);
+               free_tzi = 1;
        } else {
                tzi = get_timezone_info(TSRMLS_C);
        }
@@ -1194,7 +1237,9 @@ PHP_FUNCTION(date_create)
        if (now->tz_info != tzi) {
                timelib_tzinfo_dtor(now->tz_info);
        }
-       timelib_tzinfo_dtor(now->tz_info);
+       if (free_tzi) {
+               timelib_tzinfo_dtor(tzi);
+       }
        timelib_time_dtor(now); 
 }
 
@@ -1394,12 +1439,12 @@ PHP_FUNCTION(timezone_open)
                
                tzid = timelib_timezone_id_from_abbr(tz, -1, 0);
                if (tzid) {
-                       tzi = timelib_parse_tzfile(tzid, DATE_TIMEZONEDB);
+                       tzi = php_date_parse_tzfile(tzid, DATE_TIMEZONEDB TSRMLS_CC);
                }
        }
        /* Try finding the tz information as "Timezone Identifier" */
        if (!tzi) {
-               tzi = timelib_parse_tzfile(tz, DATE_TIMEZONEDB);
+               tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC);
        }
        /* If we find it we instantiate the object otherwise, well, we don't and return false */
        if (tzi) {
@@ -1545,7 +1590,6 @@ PHP_FUNCTION(date_default_timezone_get)
 
        default_tz = get_timezone_info(TSRMLS_C);
        RETVAL_STRING(default_tz->name, 1);
-       timelib_tzinfo_dtor(default_tz);
 }
 /* }}} */
 
index c40c451bee8b74ebab279c03fcf2433f66c16ea6..a564fc7a2497cb79d958ef3f83fa72b0ae8cf431 100644 (file)
@@ -22,6 +22,7 @@
 #define PHP_DATE_H
 
 #include "lib/timelib.h"
+#include "Zend/zend_hash.h"
 
 extern zend_module_entry date_module_entry;
 #define phpext_date_ptr &date_module_entry
@@ -77,8 +78,9 @@ PHP_MSHUTDOWN_FUNCTION(date);
 PHP_MINFO_FUNCTION(date);
 
 ZEND_BEGIN_MODULE_GLOBALS(date)
-       char *default_timezone;
-       char *timezone;
+       char      *default_timezone;
+       char      *timezone;
+       HashTable  tzcache;
 ZEND_END_MODULE_GLOBALS(date)
 
 #ifdef ZTS