PHP 5.4更新内容:
根据date_default_timezone_get
的说明,从PHP 5.4.0开始,从系统信息中猜测时区的算法已从代码中删除(与PHP 5.3代码相比)。因此,这种行为已不再存在。
在我的开发服务器上运行定时测试以查看其运作情况,结果如下:
- PHP 5.3.11:约720毫秒
- PHP 5.4.3:约470毫秒
原始答案:
我刚刚查看了PHP源代码。具体而言,所有相关代码都在/ext/date/php_date.c
中。
我假设如果您没有为date
提供时区,则会调用date_default_timezone_get
来获取时区。这是该函数:
PHP_FUNCTION(date_default_timezone_get)
{
timelib_tzinfo *default_tz;
default_tz = get_timezone_info(TSRMLS_C);
RETVAL_STRING(default_tz->name, 1);
}
好的,那么get_timezone_info
看起来是什么样子?可以参考这里:
PHPAPI timelib_tzinfo *get_timezone_info(TSRMLS_D)
{
char *tz;
timelib_tzinfo *tzi;
tz = guess_timezone(DATE_TIMEZONEDB TSRMLS_CC);
tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC);
if (! tzi) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Timezone database is corrupt - this should *never* happen!");
}
return tzi;
}
那么 guess_timezone
怎么样呢? 这里 是相关内容:
static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC)
{
char *env;
if (DATEG(timezone) && (strlen(DATEG(timezone)) > 0)) {
return DATEG(timezone);
}
env = getenv("TZ");
if (env && *env && timelib_timezone_id_is_valid(env, tzdb)) {
return env;
}
#if HAVE_TM_ZONE
#endif
#ifdef PHP_WIN32
#elif defined(NETWARE)
#endif
php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We had to select 'UTC' because your platform doesn't provide functionality for the guessing algorithm");
return "UTC";
}
好的,那么它是如何与 date_default_timezone_set
交互的呢? 我们来看看这个函数:
PHP_FUNCTION(date_default_timezone_set)
{
char *zone;
int zone_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &zone, &zone_len) == FAILURE) {
RETURN_FALSE;
}
if (!timelib_timezone_id_is_valid(zone, DATE_TIMEZONEDB)) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Timezone ID '%s' is invalid", zone);
RETURN_FALSE;
}
if (DATEG(timezone)) {
efree(DATEG(timezone));
DATEG(timezone) = NULL;
}
DATEG(timezone) = estrndup(zone, zone_len);
RETURN_TRUE;
}
长话短说:如果您只调用一次
date_default_timezone_set
,那么
guess_timezone
会采用快速路线从
timezone
变量中读取(满足第一个条件并立即返回)。否则,它需要花费一些时间来确定默认时区,该时区未被缓存(我猜是为了简单起见),如果在循环中执行此操作,则延迟开始显示。