Конвертация временных меток в локальное время с помощью date_l18n()

5 апр. 2013 г., 21:48:15
Просмотры: 40.7K
Голосов: 19

У меня есть cron-задача WordPress, которая периодически отправляет email и сохраняет временную метку отправки как опцию. Я хочу отобразить дату на странице настроек. Что-то вроде "Последнее письмо было отправлено 'x'". Я нахожусь на западном побережье США, поэтому наше время сейчас отличается на семь часов от UTC.

Ожидаемый результат от date_i18n() при передаче временной метки должен быть локально отформатированной датой с поправкой на семь часов от UTC. Однако функция возвращает время в UTC. Даже при попытке получить текущее время результат не соответствует ожидаемому.

Например: echo date_i18n('F d, Y H:i'); выводит April 05, 2013 11:36 как ожидалось, но echo date_i18n('F d, Y H:i',time()); выводит April 05, 2013 18:36.

Это задумано? Как я могу получить локально отформатированную дату из существующей временной метки? Спасибо за любую помощь.

2
Комментарии

Вы установили свой часовой пояс в Настройки->Общие?

vancoder vancoder
5 апр. 2013 г. 22:16:15

Да, на Лос-Анджелес.

Andrew Bartel Andrew Bartel
5 апр. 2013 г. 22:51:14
Все ответы на вопрос 7
3
36

Я знаю, что опаздываю на три месяца, но функция, которая вам здесь нужна, это get_date_from_gmt() WordPress.

Функция принимает дату в формате GMT/UTC Y-m-d H:i:s в качестве первого параметра и желаемый формат даты в качестве второго параметра. Она преобразует вашу дату в локальный часовой пояс, установленный на экране настроек.

Пример использования:

echo get_date_from_gmt( date( 'Y-m-d H:i:s', $my_unix_timestamp ), 'F j, Y H:i:s' );

20 июл. 2013 г. 17:37:46
Комментарии

Огромное спасибо, только что увидел это уведомление. Я изменил его на правильный ответ.

Andrew Bartel Andrew Bartel
22 июл. 2013 г. 21:45:11

Я добавил конфигурацию даты и времени: echo get_date_from_gmt ( date( 'Y-m-d H:i:s', $my_timestamp ), get_option('date_format') . ' - '. get_option('time_format') );

Nabil Kadimi Nabil Kadimi
22 июл. 2014 г. 02:31:05

@NabilKadimi это отличное дополнение, но оно всё равно не переводит строку на правильный язык. Смотрите мой ответ для функции, которая учитывает все три настроенных параметра: язык, часовой пояс и формат даты.

Flimm Flimm
30 мая 2019 г. 21:13:34
7

Из кодекса:

current_time('timestamp') следует использовать вместо time(), чтобы получить локальное время блога. В WordPress PHP-функция time() всегда возвращает время в UTC и эквивалентна вызову current_time('timestamp', true).

Попробуйте так:

define( 'MY_TIMEZONE', (get_option( 'timezone_string' ) ? get_option( 'timezone_string' ) : date_default_timezone_get() ) );
date_default_timezone_set( MY_TIMEZONE );
echo date_i18n('F d, Y H:i', 1365194723);

Это устанавливает временную зону PHP по умолчанию на значение опции timezone_string в WordPress (если оно доступно) на время выполнения скрипта.

5 апр. 2013 г. 22:18:12
Комментарии

Правильно, но что если у меня произвольная временная метка? Например, пару дней назад, как мне получить скорректированное время вместо UTC?

Andrew Bartel Andrew Bartel
5 апр. 2013 г. 22:49:06

Разве date_i18n('F d, Y H:i', $your_timestamp) не работает?

vancoder vancoder
5 апр. 2013 г. 23:41:18

Нет, даже попробовал на чистой установке WP с 2012, просто выполнив этот echo date_i18n('F d, Y H:i',1365194723) код в начале index.php, он выдает UTC вместо времени Западного побережья США.

Andrew Bartel Andrew Bartel
5 апр. 2013 г. 23:47:57

Вы правы, похоже, что date_i18n в основном предназначена для локального форматирования дат, а не для их корректировки. Я обновил свой ответ.

vancoder vancoder
6 апр. 2013 г. 00:01:10

Да, я надеялся избежать необходимости вручную устанавливать часовой пояс, но если это единственный способ, что ж. Отмечено как отвеченное, спасибо за помощь.

Andrew Bartel Andrew Bartel
6 апр. 2013 г. 00:21:52

WordPress вызывает date_default_timezone_set( 'UTC' );, и кажется плохой идеей переопределять это, вызывая date_default_timezone_set самостоятельно, так как код WordPress и плагины могут полагаться на это поведение.

Flimm Flimm
30 мая 2019 г. 19:39:29

@Flimm абсолютно прав, НИКОГДА не изменяйте настройки часового пояса по умолчанию.

Walf Walf
30 июн. 2022 г. 10:10:13
Показать остальные 2 комментариев
0

date_i18n($format, $timestamp) форматирует дату с учетом локали, но не учитывает часовой пояс. get_date_from_gmt($datestring, $format) форматирует с учетом часового пояса, но не локали. Чтобы получить форматирование с учетом и часового пояса, и локали, я использую следующий код:

function local_date_i18n($format, $timestamp) {
    $timezone_str = get_option('timezone_string') ?: 'UTC';
    $timezone = new \DateTimeZone($timezone_str);

    // Дата в локальном часовом поясе.
    $date = new \DateTime(null, $timezone);
    $date->setTimestamp($timestamp);
    $date_str = $date->format('Y-m-d H:i:s');

    // Предполагаем, что локальная дата - это UTC, чтобы получить timestamp,
    // который передается в date_i18n().
    $utc_timezone = new \DateTimeZone('UTC');
    $utc_date = new \DateTime($date_str, $utc_timezone);
    $timestamp = $utc_date->getTimestamp();

    return date_i18n($format, $timestamp, true);
}

Пример программы:

$format = 'F d, Y H:i';
$timestamp = 1365186960;
$local = local_date_i18n($format, $timestamp);
$gmt = date_i18n($format, $timestamp);
echo "Местное: ", $local, " UTC: ", $gmt;

Вывод для часового пояса Лос-Анджелеса:

Местное: April 05, 2013 11:36 UTC: April 05, 2013 18:36

Ссылки:

18 февр. 2014 г. 17:34:39
0

Конвертация UTC в строку с учетом часового пояса, языка и формата в настройках WordPress

Я создал хорошо документированную функцию, которая преобразует строку даты-времени в UTC в удобочитаемую строку с правильным языком, форматом и часовым поясом. Можете свободно использовать её.

Например, передав "2019-05-30 18:06:01" (в UTC), функция вернет "30 мая 2019 г., 10:06 am".

/**
 * Преобразует строку с датой и временем в UTC в удобочитаемую строку 
 * с учетом настроек языка, формата и часового пояса в WordPress.
 *
 * @param string $utc_date_and_time 
 *      Пример: "2019-05-30 18:06:01"
 *      Аргумент должен быть в формате UTC.
 * @return string 
 *      Пример: "30 мая 2019 г., 10:06 am"
 *      Возвращает удобочитаемую строку даты-времени на правильном языке
 *      в соответствии с настройками администратора.
 */
function pretty_utc_date( string $utc_date ): string {
    if (! preg_match( '/^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$/', $utc_date ) ) {
        /* Другие форматы не тестировались, поэтому разрешен только этот. */
        throw new InvalidArgumentException( "Ожидается аргумент в формате YYYY-MM-DD hh:mm:ss" );
    }

    $date_in_local_timezone = get_date_from_gmt( $utc_date );

    /* Теперь $date_in_local_timezone содержит что-то вроде "2019-05-30 10:06:01"
     * в часовом поясе из get_option( 'timezone_string' ), который настраивается
     * в общих настройках WordPress в админке.
     */

    /* К сожалению, мы не можем просто передать это в date_i18n WordPress, так как
     * эта функция ожидает вторым аргументом количество секунд с 1/Jan/1970
     * 00:00:00 в часовом поясе из get_option( 'timezone_string' ), что отличается
     * от UNIX timestamp, который считает секунды с 1/Jan/1970 00:00:00 GMT. */
    $seconds_since_local_1_jan_1970 =
        (new DateTime( $date_in_local_timezone, new DateTimeZone( 'UTC' ) ))
        ->getTimestamp();
    // Пример: 1559210761

    /* Администраторы могут задать предпочтительный формат даты и времени
     * в общих настройках WordPress в админке, нам нужно получить их. */
    $settings_format = get_option( 'date_format' ) . ' '. get_option( 'time_format' );
    // В этом примере $settings_format будет "F j, Y g:i a"

    /* В этом примере WordPress установлен на итальянский,
     * и конечный результат будет "30 maggio 2019 10:06 am" */
    return date_i18n( $settings_format, $seconds_since_local_1_jan_1970 );

}

Ссылки:

  • Документация WordPress по get_date_from_gmt
  • Документация PHP по DateTimeZone на php.net
  • Документация PHP по DateTime на php.net, включая getTimestamp
  • Документация WordPress по date_i18n
  • Важно помнить, что WordPress выполняет date_default_timezone_set( 'UTC' ); независимо от выбранного администратором часового пояса в интерфейсе, учитывайте это при работе со встроенными функциями PHP. См. документацию по date_default_timezone_set на php.net.
30 мая 2019 г. 21:12:41
3

Метки времени (timestamp) не содержат информации о часовом поясе, поэтому почти никогда не требуется выполнять над ними математические операции.

Начиная с WordPress версии 5.3, самое простое решение для работы с конкретными метками времени — это функция wp_date():

$format = get_option( 'time_format' ) . ', ' . get_option( 'date_format' );
echo wp_date( $format, $your_timestamp );

Для получения текущих даты и времени используйте соответствующую функцию current_datetime:

echo current_datetime()->format( $format );
30 июн. 2022 г. 10:54:43
Комментарии

Метки времени (timestamp) представляют собой количество секунд, прошедших с 1 января 1970 года 00:00 UTC в некоторых определениях, или количество секунд с 1 января 1970 года в локальном часовом поясе в других определениях.

Flimm Flimm
30 июн. 2022 г. 13:14:29

@Flimm В PHP (и, следовательно, в WordPress) метки времени всегда указываются по времени GMT. См. time().

Walf Walf
1 июл. 2022 г. 07:39:00

Это правильный ответ по состоянию на 2024 год.

Ciantic Ciantic
7 мар. 2024 г. 17:01:20
0

Добавьте смещение часового пояса к вашей временной метке.

$offset = get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
return date_i18n( get_option( 'date_format' ), $ts + $offset );

Или лучше:

$tz = new DateTimeZone( get_option( 'timezone_string' ) );
$offset_for_that_time = timezone_offset_get ( $tz , new DateTime("@{$ts}") );
return date_i18n ( get_option( 'date_format' ), $ts + $offset_for_that_time );
16 февр. 2015 г. 04:24:48
1

Этот вариант работает на моей машине (ничего другое не сработало):

$tz = new DateTimeZone(get_option('timezone_string'));
$dtz = new DateTimeZone('GMT');
foreach($posts as $key => $post){
    $gmt_date = DateTime::createFromFormat('Y-m-d H:i:s', $post->PostDateGMT, $dtz);
    $gmt_date->setTimeZone($tz);
    $posts[$key]->PostDateGMT = $gmt_date->format('Y-m-d H:i:s');
}

Оригинальный код: https://www.simonholywell.com/post/2013/12/convert-utc-to-local-time/

Здесь не используется date_l18n(), но, думаю, можно применить её позже...

28 дек. 2015 г. 20:33:52
Комментарии

get_the_time принимает аргумент $post примерно с 2008 года.

Walf Walf
30 июн. 2022 г. 11:05:56