¿Cómo obtener la configuración de zona horaria en WordPress?
¿Alguien puede decirme cómo obtener la zona horaria que está configurada en el Administrador de WordPress?
Por ejemplo, si el blog está configurado en hora del Este, necesito que se muestre exactamente esta cadena:
US/Eastern
Esto es para una función que vive en functions.php en mi tema.

Mi timezone_string está en la base de datos pero está vacío, incluso después de seleccionar una zona horaria diferente en la página de configuración. ¿Cuál podría ser el caso? (WP3.6)

¿El gmt_offset tiene en cuenta el horario de verano basado en la configuración de zona horaria del sitio?

La situación desafortunada es que en realidad existen dos opciones diferentes:
- El más reciente
timezone_string
, que guarda la zona horaria en formato PHP. - El más antiguo
gmt_offset
, que guarda un desplazamiento numérico en horas (float).
Pero en entornos más nuevos, timezone_string
en realidad anula a gmt_offset
, y el valor devuelto por este último se basará en el primero. Sin embargo, lo contrario no es cierto: gmt_offset
podría ser válido mientras que timezone_string
esté vacío.
WordPress 5.3 incluyó la función wp_timezone()
, que abstrae esto y devuelve un objeto DateTimeZone
válido, independientemente de la configuración subyacente de WP.
Antes de eso, yo había implementado un enfoque en mi biblioteca WpDateTime
(como dato curioso, esto sirvió como base para la implementación en el núcleo):
class WpDateTimeZone extends \DateTimeZone {
/**
* Determina la zona horaria a partir de las opciones de WordPress y la devuelve como objeto.
*
* @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 );
}
}

Esta debería ser la respuesta aceptada. La gente encontrará errores si confían únicamente en get_option('timezone_string').

¿No es problemático el uso de (int)
para $hours y floor
para $minutes? Según la documentación, (int)
y floor
son casi iguales excepto que (int)
redondeará -4.5 a -4 y floor
lo redondeará a -5. ¿Esto no daría como resultado desplazamientos de zona horaria negativos incorrectos?

@Mikepote sí, esto se solucionó en la librería hace mucho tiempo, solo es una copia desactualizada del código en la respuesta aquí.

Dios mío, ¿por qué lo implementaron así...? Me costó una hora entera de frustración

¿La librería maneja el hecho de que una zona horaria puede contener múltiples desplazamientos? Ver: https://stackoverflow.com/tags/timezone/info

Consulta la página de referencia de opciones. La opción gmt_offset
devuelve un número entero. Por ejemplo, si la zona horaria está configurada en hora del Este (por ejemplo, America/New_York), gmt_offset
debería ser -5.

Dado que WordPress guarda la cadena de zona horaria en la tabla de opciones, puedes usar el enfoque orientado a objetos para obtener la hora correcta en tu sitio de WordPress:
$tz = new DateTimeZone(get_option('timezone_string'));
$dt = new DateTime("now", $tz);
$page .= "<p> Fecha y Hora " . $dt->format("Y-m-d H:i:s") . "</p>";

No creas que vas a obtener una cadena como US/Eastern sin almacenar todas las cadenas que necesitas en un array y referenciarlas. Usando PHP puedes obtener la abreviatura de la zona horaria, es decir EST; y si tienes esos valores almacenados en un array con las cadenas que deseas, puedes buscarlas.
<?php date_default_timezone_set(get_option('timezone_string'));
echo date('T'); // te dará una cadena de tres caracteres como "EST"
$timezones = array (
'EST' => 'US/Eastern',
'CST' => 'US/Central',
// etc, etc, etc.
);
echo $timezones [ date('T') ]; // debería ser lo que buscas.
?>

Esto es innecesario. Los estándares de zona horaria han sido parte de PHP desde la versión 5.2, al igual que el objeto DateTimeZone y las funciones estándar relacionadas.

Para agregar a Bainternet (estoy publicando esto como respuesta porque no puedo comentar - tengo menos de 50 puntos en el stack de Desarrollo de WP).
WordPress solo almacenará una cadena de zona horaria si seleccionas una cadena de zona horaria en los ajustes generales. La selección UTC es donde aparece por defecto en la lista, pero puedes desplazarte hacia arriba para ver las cadenas de zona horaria. Si configuras una cadena de zona horaria, tanto el UTC como la cadena de zona horaria se establecerán. Serán lo mismo (es decir, el UTC se restablece a la nueva zona cuando seleccionas una zona horaria basada en cadena).
(WordPress 4)

Como mencionó Rarst, ahora puedes usar wp_timezone()
que devuelve un objeto de zona horaria.
O para obtener la zona horaria como una cadena, wp_timezone_string()
, que devuelve 'Europe/Rome', 'UTC', o el desplazamiento UTC como '-6:00'.
Y si deseas la abreviatura, wp_date('T')
también devuelve la zona horaria localizada.

Hay algunas opciones, ninguna de las cuales funciona realmente bien. Este es un error de WordPress, y realmente es molesto porque la hora es incorrecta a menos que configures tu sitio en UTC... lo cual es confuso y no siempre es posible.
El siguiente código creo que solo funciona si eliges tu zona horaria (en Ajustes -> General en el administrador) como una ciudad con nombre en lugar de un desplazamiento numérico GMT. No lo he probado, pero es muy posible que get_option('gmt_offset')
esté configurado cuando get_option('timezone_string')
no lo esté.
date_default_timezone_set(get_option('timezone_string'));
El inconveniente de esto es que WordPress asume que PHP está configurado en UTC al crear marcas de tiempo de MySQL, por lo que puedes desordenar un poco tu base de datos cada vez que cambias de zona horaria. Sin mencionar que otros plugins de WP pueden asumir que el entorno de PHP siempre está en UTC.
Entonces, si solo quieres una hora correcta, puedes forzar tu marca de tiempo a UTC con:
get_post_time('c', true); // debería funcionar para objetos que no son posts.
Desafortunadamente, aunque es correcto, hará que la zona horaria se establezca en UTC.
Y ten en cuenta que no puedes tanto usar el flag "true" como la función timezone_set por defecto.
Cualquier solución adecuada será un fragmento de código que tenga en cuenta tanto gmt_offset
como timezone_string
y los use para establecer una zona horaria en alguna entrada. WP asume que PHP está configurado en UTC al hacer marcas de tiempo de MySQL, y podría romper otros plugins.
Hay una solución de este tipo en https://www.skyverge.com/blog/down-the-rabbit-hole-wordpress-and-timezones/ pero, de nuevo, esto es un ERROR, por lo que deberías usar el código get_post_time($date_format, TRUE)
para obtener una marca de tiempo que sea realmente correcta.
