Как получить настройку часового пояса WordPress?
Может кто-нибудь подсказать, как получить часовой пояс, который установлен в панели администратора WordPress?
Например, если блог настроен на восточное время, мне нужно, чтобы выводилась именно эта строка:
US/Eastern
Это для функции, которая находится в файле functions.php моей темы.

Если вам нужно смещение GMT, тогда используйте:
<?php echo get_option('gmt_offset'); ?>
Это вернет целое число, например 2 или -2.
А если вам нужна строковая версия часового пояса, используйте:
<?php echo get_option('timezone_string'); ?>
Это вернет строку в формате America/Indianapolis

Мой параметр timezone_string есть в базе данных, но он пуст, даже после выбора другой временной зоны на странице настроек. В чем может быть причина? (WP3.6)

Учитывает ли gmt_offset летнее время на основе настроек временной зоны сайта?

К сожалению, действительно существует два разных варианта:
- Более новый
timezone_string
, который сохраняет временную зону в стиле PHP. - Более старый
gmt_offset
, который сохраняет числовое смещение в часах (float).
Но в новых средах timezone_string
фактически переопределяет gmt_offset
— возвращаемое значение последнего будет основано на первом. Однако обратное неверно — gmt_offset
может быть действительным, в то время как timezone_string
может быть пустым.
В WordPress 5.3 была добавлена функция wp_timezone()
, которая абстрагирует эту логику и возвращает валидный объект DateTimeZone
, независимо от базовых настроек WordPress.
До этого у меня была собственная реализация в моей WpDateTime
библиотеке (интересный факт: она послужила основой для реализации в ядре WordPress):
class WpDateTimeZone extends \DateTimeZone {
/**
* Определяет временную зону из настроек WordPress и возвращает её в виде объекта.
*
* @return static
*/
public static function getWpTimezone() {
$timezone_string = get_option( 'timezone_string' );
if ( ! empty( $timezone_string ) ) {
return new static( $timezone_string );
}
$offset = get_option( 'gmt_offset' );
$hours = (int) $offset;
$minutes = abs( ( $offset - (int) $offset ) * 60 );
$offset = sprintf( '%+03d:%02d', $hours, $minutes );
return new static( $offset );
}
}

Это должен быть принятый ответ. Люди столкнутся с ошибками, если будут полагаться только на get_option('timezone_string').

Разве использование (int)
для $hours и floor
для $minutes не проблематично? Согласно документации, (int)
и floor
почти одинаковы, за исключением того, что (int)
округлит -4.5 до -4, а floor
округлит до -5. Кажется, это может дать некорректные отрицательные смещения временных зон?

@Mikepote да, это было исправлено в библиотеке давно, просто устаревшая версия кода в ответе здесь.

О боже, зачем они так это реализовали... Это стоило мне целого часа раздражения

Учитывает ли библиотека тот факт, что в одном часовом поясе может быть несколько смещений? Смотри: https://stackoverflow.com/tags/timezone/info

Проверьте страницу справочника опций. Опция gmt_offset
возвращает целое число. Например, если часовой пояс установлен на Восточное время (например, America/New_York), gmt_offset
должен быть равен -5.

Учитывая, что WordPress хранит строку часового пояса в таблице опций, вы можете использовать объектно-ориентированный способ для получения правильного времени на вашем сайте WordPress:
$tz = new DateTimeZone(get_option('timezone_string'));
$dt = new DateTime("now", $tz);
$page .= "<p> DateTime " . $dt->format("Y-m-d H:i:s") . "</p>";

Не думайте, что вы получите строку типа US/Eastern, не сохранив все нужные строки в массив и не обращаясь к ним. Используя PHP, вы можете получить аббревиатуру часового пояса, например EST; и если у вас есть эти значения, сохраненные в массиве с нужными строками, вы можете их использовать.
<?php date_default_timezone_set(get_option('timezone_string'));
echo date('T'); // вернёт трёхсимвольную строку, например "EST"
$timezones = array (
'EST' => 'US/Eastern',
'CST' => 'US/Central',
// и так далее...
);
echo $timezones [ date('T') ]; // должно вернуть то, что вам нужно.
?>

Это излишне. Стандарты временных зон являются частью PHP начиная с версии 5.2, как и объект DateTimeZone вместе с соответствующими стандартными функциями.

Дополнение к Bainternet (я добавляю это в качестве ответа, так как не могу оставить комментарий — у меня меньше 50 баллов на WP Development Stack).
WordPress сохраняет строку часового пояса только в том случае, если вы выбираете её в общих настройках. По умолчанию в списке выбрано значение UTF, но вы можете прокрутить вверх и выбрать строку часового пояса. Если вы установите строку часового пояса, будут сохранены как UTF, так и сама строка часового пояса. Они будут одинаковыми (то есть UTF сбрасывается на новую зону при выборе строки часового пояса).
(WordPress 4)

Как сказал Rarst, теперь вы можете использовать wp_timezone()
, который возвращает объект временной зоны.
Или, чтобы получить временную зону в виде строки, используйте wp_timezone_string()
— он возвращает значения в формате 'Europe/Moscow', 'UTC' или смещение UTC, например '+3:00'.
А если вам нужно сокращенное обозначение, wp_date('T')
также возвращает локализованное обозначение временной зоны.

Есть несколько вариантов, но ни один из них не работает идеально. Это баг WordPress, и он действительно раздражает, потому что время отображается неверно, если вы не установите для своего сайта UTC... что сбивает с толку и не всегда возможно.
Следующий код, вероятно, работает только если вы выбрали свою временную зону (в разделе Настройки → Общие в админке) по названию города, а не по смещению GMT. Я не проверял, но вполне возможно, что get_option('gmt_offset')
установлен, а get_option('timezone_string')
— нет.
date_default_timezone_set(get_option('timezone_string'));
Недостаток в том, что WordPress предполагает, что PHP настроен на UTC при создании временных меток MySQL, поэтому при смене часовых поясов можно немного испортить базу данных! Не говоря уже о том, что другие плагины WordPress могут полагаться на то, что среда PHP всегда работает в UTC.
Если вам просто нужно правильное время — можно принудительно установить временную метку в UTC:
get_post_time('c', true); //должно работать для объектов, не являющихся записями.
К сожалению, хотя время будет верным, часовой пояс будет установлен в UTC.
И учтите, что нельзя использовать одновременно флаг "true" и функцию date_default_timezone_set()
.
Любое правильное решение — это фрагмент кода, учитывающий и gmt_offset
, и timezone_string
, и использующий их для установки часового пояса. WordPress предполагает, что PHP работает в UTC при работе с временными метками MySQL, и это может сломать другие плагины.
Одно из таких решений есть на https://www.skyverge.com/blog/down-the-rabbit-hole-wordpress-and-timezones/, но, повторюсь, это БАГ, поэтому лучше использовать код get_post_time($date_format, TRUE)
, чтобы получать временные метки, которые действительно верны.
