es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Tratando de obtener marcas de tiempo de Carbon en diferentes zonas horarias.

Ejecutamos una aplicación Laravel con una base de datos MySQL. La base de datos consiste en muchas entradas relacionadas con diferentes proyectos. La idea es que cada proyecto tiene su propia zona horaria y muestra las entradas relevantes con las fechas formateadas en consecuencia. Por lo tanto, para poder cambiar las zonas horarias y para mayor compatibilidad, todas las entradas se almacenan en la zona horaria UTC (la zona horaria predeterminada de la aplicación también está configurada en UTC).
El problema es que, por ejemplo, necesitamos obtener las entradas de hoy, pero en la zona horaria del proyecto, no en UTC. Usamos Carbon, pero solo formatea la fecha para la salida y aún las compara en la zona horaria UTC.
Por ejemplo, hay una entrada realizada el 7 de diciembre a las 22:32 en UTC. Pero según Europe/Moscow, se hizo el 8 de diciembre a las 01:32, y debería considerarse como la entrada de hoy para un proyecto con la zona horaria Europe/Moscow. Sin embargo, incluso con la zona horaria de Moscú dada, Carbon la considera como la entrada de ayer (según UTC). Usamos whereDate en la consulta:

whereDate('created_at', Carbon::now($project->timezone)->startOfDay())

El problema es que Carbon no hace ninguna diferencia entre Carbon::now('UTC') y Carbon::now('Europe/Moscow'). Da cero si los comparas:

$tz1 = Carbon::now('UTC');
$tz2 = Carbon::now('Europe/Moscow');
echo $tz1->diffInHours($tz2); // 0

¿Qué me estoy perdiendo? ¿Cómo debo hacerlo correctamente?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para manejar adecuadamente las conversiones de zona horaria en una aplicación de Laravel con una base de datos MySQL, hay algunas cosas a tener en cuenta. En primer lugar, guarde todas las marcas de tiempo en la zona horaria UTC para garantizar la compatibilidad en diferentes regiones horarias. Luego, al consultar las entradas en la zona horaria específica de un proyecto, convierta la marca de tiempo UTC a la zona horaria relevante utilizando la biblioteca Carbon.

    En el código proporcionado, el problema es que Carbon::now() devuelve la hora actual en la zona horaria del servidor, que probablemente esté configurada en UTC. Para obtener la hora actual en la zona horaria especificada, use Carbon::now($project->timezone) en su lugar.

    Para obtener las entradas de hoy en la zona horaria del proyecto, use el siguiente código:

    whereDate(
        DB::raw("CONVERT_TZ(created_at, '+00:00', '{$project->timezone}')"),
        Carbon::now($project->timezone)->startOfDay()
    )
    

    La función CONVERT_TZ de MySQL convierte la marca de tiempo created_at de UTC a la zona horaria del proyecto, y la función whereDate filtra las entradas creadas en el día actual de esa zona horaria.

    Para evitar problemas con los cambios de horario de verano, se recomienda almacenar nombres de zonas horarias en lugar de desplazamientos, ya que los desplazamientos pueden cambiar según la época del año.

Comments are closed.