Convirtiendo marcas de tiempo a hora local con date_l18n()

5 abr 2013, 21:48:15
Vistas: 40.7K
Votos: 19

Tengo un trabajo cron de WordPress que envía un correo electrónico periódicamente y guarda la marca de tiempo cuando fue enviado como una opción, y me gustaría mostrar una fecha en una página de configuración. Algo como "El último correo electrónico fue enviado el 'x'". Estoy en la costa oeste de EE.UU., por lo que nuestra hora está actualmente siete horas desfasada de UTC.

La salida esperada de date_i18n(), pasándole la marca de tiempo, sería una fecha formateada localmente con un ajuste de siete horas desde UTC. Sin embargo, devuelve la hora en UTC. Incluso al intentar obtener la hora actual no devuelve lo que yo pensaría que sería la salida esperada.

Por ejemplo: echo date_i18n('F d, Y H:i'); muestra April 05, 2013 11:36 como se esperaba, pero echo date_i18n('F d, Y H:i',time()); muestra April 05, 2013 18:36.

¿Es esto intencional? ¿Cómo puedo devolver una fecha formateada localmente desde una marca de tiempo preexistente? Gracias por cualquier ayuda.

2
Comentarios

¿Has configurado tu zona horaria en Ajustes->Generales?

vancoder vancoder
5 abr 2013 22:16:15

Sí, a Los Ángeles.

Andrew Bartel Andrew Bartel
5 abr 2013 22:51:14
Todas las respuestas a la pregunta 7
3
36

Sé que llego tres meses tarde, pero la función que buscas aquí es get_date_from_gmt() de WordPress.

La función acepta una fecha GMT/UTC en formato Y-m-d H:i:s como primer parámetro y el formato de fecha deseado como segundo parámetro. Convertirá tu fecha a la zona horaria local configurada en la pantalla de Ajustes.

Ejemplo de uso:

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

20 jul 2013 17:37:46
Comentarios

Mil gracias, acabo de ver esta notificación emergente. Lo cambié a la respuesta correcta.

Andrew Bartel Andrew Bartel
22 jul 2013 21:45:11

Agregué la configuración de fecha y hora: 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 jul 2014 02:31:05

@NabilKadimi ese es un gran añadido, pero aún no traduce el string al idioma correcto. Mira mi respuesta para ver una función que tiene en cuenta los tres elementos configurados: idioma, zona horaria y formato de fecha.

Flimm Flimm
30 may 2019 21:13:34
7

Del codex:

current_time('timestamp') debería usarse en lugar de time() para devolver la hora local del blog. En WordPress, PHP time() siempre devolverá UTC y es lo mismo que llamar a current_time('timestamp', true).

Prueba esto:

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);

Esto establece la fecha predeterminada de PHP a la opción timezone_string de WP, si está disponible, durante la ejecución del script.

5 abr 2013 22:18:12
Comentarios

Correcto, pero ¿qué pasa si tengo una marca de tiempo arbitraria? Digamos de hace un par de días, ¿cómo obtengo la hora ajustada en lugar de la hora UTC?

Andrew Bartel Andrew Bartel
5 abr 2013 22:49:06

¿No funciona date_i18n('F d, Y H:i', $your_timestamp)?

vancoder vancoder
5 abr 2013 23:41:18

No, incluso lo probé en una instalación limpia de WP con 2012 ejecutando esta declaración echo date_i18n('F d, Y H:i',1365194723) al principio de index.php, eso me da UTC en lugar de la hora de la Costa Oeste de EE.UU.

Andrew Bartel Andrew Bartel
5 abr 2013 23:47:57

Tienes razón, parece que date_i18n es principalmente para el formateo local de fechas, en lugar del ajuste de fechas. He actualizado mi respuesta.

vancoder vancoder
6 abr 2013 00:01:10

Sí, esperaba evitar tener que configurar la zona horaria manualmente, pero si esa es la única manera, así será. Marcado como respondido, gracias por la ayuda.

Andrew Bartel Andrew Bartel
6 abr 2013 00:21:52

WordPress llama a date_default_timezone_set( 'UTC' );, parece una mala idea anular esto llamando a date_default_timezone_set tú mismo, ya que el código de WordPress y los plugins podrían depender de ese comportamiento.

Flimm Flimm
30 may 2019 19:39:29

@Flimm tiene razón aquí, NUNCA cambies la configuración de zona horaria predeterminada.

Walf Walf
30 jun 2022 10:10:13
Mostrar los 2 comentarios restantes
0

date_i18n($format, $timestamp) formatea según el idioma local, pero no según la zona horaria. get_date_from_gmt($datestring, $format) formatea según la zona horaria, pero no según el idioma local. Para obtener un formato que respete tanto la zona horaria como el idioma local, estoy haciendo lo siguiente:

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

    // La fecha en la zona horaria local.
    $date = new \DateTime(null, $timezone);
    $date->setTimestamp($timestamp);
    $date_str = $date->format('Y-m-d H:i:s');

    // Suponer que la fecha local es UTC para obtener el timestamp
    // que pasaremos a 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);
}

Ejemplo de programa:

$format = 'F d, Y H:i';
$timestamp = 1365186960;
$local = local_date_i18n($format, $timestamp);
$gmt = date_i18n($format, $timestamp);
echo "Local: ", $local, " UTC: ", $gmt;

Salida para la zona horaria de Los Ángeles:

Local: Abril 05, 2013 11:36 UTC: Abril 05, 2013 18:36

Referencias:

18 feb 2014 17:34:39
0

Convertir UTC a cadena en zona horaria, idioma y formato según las opciones de WordPress

He creado una función bien documentada que convierte una cadena de fecha y hora en UTC a una cadena de fecha y hora legible en el idioma, formato y zona horaria correctos. Siéntete libre de copiarla.

Por ejemplo, al pasar "2019-05-30 18:06:01" (en UTC) devolvería "Mayo 30, 2019 10:06 am".

/**
 * Dada una cadena con la fecha y hora en UTC, devuelve una cadena legible en el
 * idioma, formato y zona horaria configurados en las opciones de WordPress.
 *
 * @param string $utc_date_and_time 
 *      ej: "2019-05-30 18:06:01"
 *      Este argumento debe estar en UTC.
 * @return string 
 *      ej: "Mayo 30, 2019 10:06 am"
 *      Devuelve una cadena de fecha y hora legible en el idioma correcto y
 *      siguiendo la configuración del administrador.
 */
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 ) ) {
        /* No he probado otros formatos, así que solo permito este. */
        throw new InvalidArgumentException( "Se esperaba que el argumento esté en formato YYYY-MM-DD hh:mm:ss" );
    }

    $date_in_local_timezone = get_date_from_gmt( $utc_date );

    /* $date_in_local_timezone ahora es algo como "2019-05-30 10:06:01"
     * en la zona horaria de get_option( 'timezone_string' ), configurada en
     * los ajustes generales de WordPress en la interfaz de usuario del backend.
     */

    /* Desafortunadamente, no podemos simplemente pasar esto a date_i18n de WordPress, ya que
     * espera que el segundo argumento sea el número de segundos desde 1/Ene/1970
     * 00:00:00 en la zona horaria de get_option( 'timezone_string' ), que no es lo mismo
     * que un timestamp UNIX, que es el número de segundos desde
     * 1/Ene/1970 00:00:00 GMT. */
    $seconds_since_local_1_jan_1970 =
        (new DateTime( $date_in_local_timezone, new DateTimeZone( 'UTC' ) ))
        ->getTimestamp();
    // ej: 1559210761

    /* Los administradores pueden configurar un formato de fecha y un formato de hora
     * preferidos en los ajustes generales de WordPress en la interfaz de usuario del backend,
     * necesitamos obtener eso. */
    $settings_format = get_option( 'date_format' ) . ' '. get_option( 'time_format' );
    // $settings_format en este ejemplo es "F j, Y g:i a"

    /* En este ejemplo, la instalación de WordPress está configurada en italiano,
     * y el resultado final es "Mayo 30, 2019 10:06 am" */
    return date_i18n( $settings_format, $seconds_since_local_1_jan_1970 );

}

Referencias:

  • Documentación de get_date_from_gmt en WordPress
  • Documentación de DateTimeZone en php.net
  • Documentación de DateTime en php.net, incluyendo getTimestamp
  • Documentación de date_i18n en WordPress
  • Vale la pena recordar que WordPress ejecuta date_default_timezone_set( 'UTC' ); independientemente de la zona horaria que el administrador haya seleccionado en la interfaz de usuario, así que tenlo en cuenta al determinar el comportamiento de las funciones integradas de PHP. Ver documentación de date_default_timezone_set en php.net.
30 may 2019 21:12:41
3

Las marcas de tiempo (timestamps) no tienen zona horaria, por lo que casi nunca necesitas operar matemáticamente con ellas.

Desde WordPress 5.3, la solución más sencilla para marcas de tiempo específicas es wp_date():

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

Para la fecha y hora actual, usa la función apropiadamente llamada current_datetime:

echo current_datetime()->format( $format );
30 jun 2022 10:54:43
Comentarios

Los timestamps son el número de segundos desde el 1 de enero de 1970 00:00 UTC para algunas definiciones de timestamp, o el número de segundos desde el 1 de enero de 1970 en la zona horaria local para otras definiciones de timestamp.

Flimm Flimm
30 jun 2022 13:14:29

@Flimm En PHP (y por lo tanto en WordPress), los timestamps siempre están en GMT. Ver time().

Walf Walf
1 jul 2022 07:39:00

Esta es la respuesta correcta a partir de 2024.

Ciantic Ciantic
7 mar 2024 17:01:20
0

Añade el desplazamiento de zona horaria a tu marca de tiempo.

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

o mejor aún:

$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 feb 2015 04:24:48
1

Esto es lo que parece funcionar en mi máquina (ninguna de las otras soluciones funcionó):

$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');
}

Código original: https://www.simonholywell.com/post/2013/12/convert-utc-to-local-time/

No está usando date_l18n() pero supongo que se podría usar más adelante...

28 dic 2015 20:33:52
Comentarios

get_the_time ha aceptado un argumento $post desde aproximadamente 2008.

Walf Walf
30 jun 2022 11:05:56