Saltar al contenido

Obtener la compensación de zona horaria correcta en Python usando la zona horaria local

Este equipo de expertos luego de muchos días de investigación y recopilación de de datos, obtuvieron los datos necesarios, queremos que todo este artículo sea de gran utilidad para tu proyecto.

Solución:

Según Wikipedia, la transición hacia y desde el horario de verano se produce a las 01:00 UTC.

  • A las 00:12 UTC todavía se encuentra en el horario de verano de Europa Central (es decir, UTC + 02: 00), por lo que la hora local es 02:12.

  • A las 01:12 UTC, regresa a la hora estándar de Europa Central (es decir, UTC + 01:00), por lo que la hora local es nuevamente 02:12.

Cuando se cambia de la hora de verano a la hora estándar, la hora local va desde las 02:59 hasta las 02:00 y la hora se repite. Entonces, al preguntar por el desplazamiento UTC de 02:12 (hora local), la respuesta podría ser sinceramente +01: 00 o +02: 00, depende de qué versión de 02:12 esté hablando.

En una investigación más profunda de la biblioteca de pytz, creo que su problema puede ser que no debería usar la implementación de pytz.reference, que puede no tratar estas ambigüedades muy bien. Citando los comentarios en el código fuente:

Haga referencia a las implementaciones de tzinfo de los documentos de Python. Se utilizan para realizar pruebas, ya que solo son correctos para los años 1987 a 2006. No los utilice para código real.

Trabajando con tiempos ambiguos en pytz

Lo que deberías estar haciendo es construir un zona horaria objeto para la zona horaria adecuada:

import pytz
cet = pytz.timezone('CET')

Entonces puedes usar el utcoffset método para calcular el desplazamiento UTC de una fecha / hora en esa zona horaria.

dt = datetime.datetime(2010, 10, 31, 2, 12, 30)
offset = cet.utcoffset(dt)

Tenga en cuenta que el ejemplo anterior arrojará un AmbiguousTimeError excepción, porque no puede decir a cuál de las dos versiones de 02:12:30 te refieres. Afortunadamente, pytz le permitirá especificar si desea la versión dst o la versión estándar configurando el is_dst parámetro. Por ejemplo:

offset = cet.utcoffset(dt, is_dst = True)

Tenga en cuenta que no está de más establecer este parámetro en todas las llamadas a utcoffset, incluso si el tiempo no fuera ambiguo. Según la documentación, solo se utiliza durante los períodos ambiguos de transición del horario de verano para resolver esa ambigüedad.

Cómo lidiar con las marcas de tiempo

En cuanto al manejo de las marcas de tiempo, es mejor que las almacene como valores UTC durante el mayor tiempo posible, de lo contrario, posiblemente termine tirando información valiosa. Así que primero convierta a una fecha y hora UTC con el datetime.utcfromtimestamp método.

dt = datetime.datetime.utcfromtimestamp(1288483950)

Luego use pytz para localizar la hora como UTC, por lo que la zona horaria se adjunta al objeto de fecha y hora.

dt = pytz.utc.localize(dt)

Finalmente, puede convertir esa fecha y hora UTC en su zona horaria local y obtener el desplazamiento de la zona horaria de la siguiente manera:

offset = dt.astimezone(cet).utcoffset()

Tenga en cuenta que este conjunto de cálculos producirá las compensaciones correctas para 1288483950 y 1288487550, aunque ambas marcas de tiempo están representadas por 02:12:30 en la zona horaria CET.

Determinar la zona horaria local

Si necesita usar la zona horaria local de su computadora en lugar de una zona horaria fija, no puede hacerlo directamente desde pytz. Tampoco puedes simplemente construir un pytz.timezone objeto usando el nombre de la zona horaria de time.tzname, porque los nombres no siempre serán reconocidos por pytz.

La solución es usar el módulo tzlocal, su único propósito es proporcionar esta funcionalidad faltante en pytz. Lo usas así:

import tzlocal
local_tz = tzlocal.get_localzone()

El get_localzone () la función devuelve un pytz.timezone objeto, por lo que debería poder usar ese valor en todos los lugares en los que he usado el cet variable en los ejemplos anteriores.

Dada una marca de tiempo en milisegundos, puede obtener el desplazamiento utc para la zona horaria local usando solo stdlib:

#!/usr/bin/env python
from datetime import datetime

millis = 1288483950000
ts = millis * 1e-3
# local time == (utc time + utc offset)
utc_offset = datetime.fromtimestamp(ts) - datetime.utcfromtimestamp(ts)

Si ignoramos el tiempo alrededor de los segundos intercalares, entonces no hay ambigüedad ni tiempos inexistentes.

Es compatible con DST y cambios de la compensación utc por otras razones si el sistema operativo mantiene una base de datos de zona horaria histórica, por ejemplo, debería funcionar en Ubuntu para cualquier fecha pasada / presente, pero podría fallar en Windows para fechas pasadas que usaron una compensación utc diferente.

Aquí está el mismo uso tzlocal módulo que debería funcionar en sistemas * nix y Win32:

#!/usr/bin/env python
from datetime import datetime
from tzlocal import get_localzone # pip install tzlocal

millis = 1288483950000
ts = millis * 1e-3
local_dt = datetime.fromtimestamp(ts, get_localzone())
utc_offset = local_dt.utcoffset()

Consulte ¿Cómo convertir una fecha y hora utc de Python en una fecha y hora local utilizando solo la biblioteca estándar de Python?

Para obtener el desplazamiento de utc en minutos (Python 3.2+):

from datetime import timedelta

minutes = utc_offset / timedelta(minutes=1)

No use pytz.reference.LocalTimezone(), es solo para pruebas.

Comentarios y valoraciones del post

Si tienes alguna suspicacia y forma de medrar nuestro escrito puedes añadir un exégesis y con gusto lo ojearemos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *