Обновление для 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
(выполняется первое условное условие, и оно немедленно возвращается).В противном случае требуется определенное время для определения часового пояса по умолчанию, который не кэшируется (я полагаю для простоты), и если вы сделаете это в цикле, задержка начнет показываться.