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;
/* Checking configure timezone */
if (DATEG(timezone) && (strlen(DATEG(timezone)) > 0)) {
return DATEG(timezone);
}
/* Check environment variable */
env = getenv("TZ");
if (env && *env && timelib_timezone_id_is_valid(env, tzdb)) {
return env;
}
/* Check config setting for default timezone */
/* ..... code omitted ....... */
#if HAVE_TM_ZONE
/* Try to guess timezone from system information */
/* ..... code omitted ....... */
#endif
#ifdef PHP_WIN32
/* ..... code omitted ....... */
#elif defined(NETWARE)
/* ..... code omitted ....... */
#endif
/* Fallback to UTC */
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