convert change python datetime timezone python-datetime

change - set timezone to datetime python



Convierta un horario de UTC de python a un horario local utilizando solo la biblioteca estándar de Python. (8)

Tengo una instancia de python datetime que se creó usando datetime.utcnow () y persistió en la base de datos.

Para mostrar, me gustaría convertir la instancia de fecha y hora recuperada de la base de datos a hora local utilizando la zona horaria local predeterminada (es decir, como si la fecha y hora se hubiera creado usando datetime.now ()).

¿Cómo puedo convertir la fecha y hora de UTC en una fecha de hora local utilizando solo la biblioteca estándar de Python (por ejemplo, no dependencia de pytz)?

Parece que una solución sería usar datetime.astimezone (tz), pero ¿cómo obtendría la zona horaria local predeterminada?


Basándose en el comentario de Alexei. Esto también debería funcionar para DST.

import time import datetime def utc_to_local(dt): if time.localtime().tm_isdst: return dt - datetime.timedelta(seconds = time.altzone) else: return dt - datetime.timedelta(seconds = time.timezone)


Creo que lo descubrí: calcula el número de segundos desde epoch, luego convierte a un timzeone local usando time.localtime, y luego convierte el tiempo struct de nuevo en un datetime ...

EPOCH_DATETIME = datetime.datetime(1970,1,1) SECONDS_PER_DAY = 24*60*60 def utc_to_local_datetime( utc_datetime ): delta = utc_datetime - EPOCH_DATETIME utc_epoch = SECONDS_PER_DAY * delta.days + delta.seconds time_struct = time.localtime( utc_epoch ) dt_args = time_struct[:6] + (delta.microseconds,) return datetime.datetime( *dt_args )

Aplica el horario de verano / invierno correctamente:

>>> utc_to_local_datetime( datetime.datetime(2010, 6, 6, 17, 29, 7, 730000) ) datetime.datetime(2010, 6, 6, 19, 29, 7, 730000) >>> utc_to_local_datetime( datetime.datetime(2010, 12, 6, 17, 29, 7, 730000) ) datetime.datetime(2010, 12, 6, 18, 29, 7, 730000)


En Python 3.3+:

from datetime import timezone def utc_to_local(utc_dt): return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)

En Python 2/3:

import calendar from datetime import datetime, timedelta def utc_to_local(utc_dt): # get integer timestamp to avoid precision lost timestamp = calendar.timegm(utc_dt.timetuple()) local_dt = datetime.fromtimestamp(timestamp) assert utc_dt.resolution >= timedelta(microseconds=1) return local_dt.replace(microsecond=utc_dt.microsecond)

Usando pytz (ambos Python 2/3):

import pytz local_tz = pytz.timezone(''Europe/Moscow'') # use your local timezone name here # NOTE: pytz.reference.LocalTimezone() would produce wrong result here ## You could use `tzlocal` module to get local timezone on Unix and Win32 # from tzlocal import get_localzone # $ pip install tzlocal # # get local timezone # local_tz = get_localzone() def utc_to_local(utc_dt): local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz) return local_tz.normalize(local_dt) # .normalize might be unnecessary

Ejemplo

def aslocaltimestr(utc_dt): return utc_to_local(utc_dt).strftime(''%Y-%m-%d %H:%M:%S.%f %Z%z'') print(aslocaltimestr(datetime(2010, 6, 6, 17, 29, 7, 730000))) print(aslocaltimestr(datetime(2010, 12, 6, 17, 29, 7, 730000))) print(aslocaltimestr(datetime.utcnow()))

Salida

Python 3.3

2010-06-06 21:29:07.730000 MSD+0400 2010-12-06 20:29:07.730000 MSK+0300 2012-11-08 14:19:50.093745 MSK+0400 Python 2

2010-06-06 21:29:07.730000 2010-12-06 20:29:07.730000 2012-11-08 14:19:50.093911 pytz

2010-06-06 21:29:07.730000 MSD+0400 2010-12-06 20:29:07.730000 MSK+0300 2012-11-08 14:19:50.146917 MSK+0400

Nota: tiene en cuenta el horario de verano y el cambio reciente de la compensación utc para la zona horaria MSK.

No sé si las soluciones que no son de pytz funcionan en Windows.


La biblioteca estándar de Python no viene con ninguna implementación de tzinfo . Siempre he considerado esto como una falla sorprendente del módulo de fecha y hora.

La documentación para la clase tzinfo viene con algunos ejemplos útiles. Busque el bloque de código grande al final de la sección.


La forma más fácil que he encontrado es obtener el desplazamiento de tiempo de donde se encuentra, luego restarlo de la hora.

def format_time(ts,offset): if not ts.hour >= offset: ts = ts.replace(day=ts.day-1) ts = ts.replace(hour=ts.hour-offset) else: ts = ts.replace(hour=ts.hour-offset) return ts

Esto funciona para mí, en Python 3.5.2.


No puede hacerlo solo con la biblioteca estándar, ya que la biblioteca estándar no tiene zonas horarias. Necesita pytz o dateutil .

>>> from datetime import datetime >>> now = datetime.utcnow() >>> from dateutil import tz >>> HERE = tz.tzlocal() >>> UTC = tz.gettz(''UTC'') The Conversion: >>> gmt = now.replace(tzinfo=UTC) >>> gmt.astimezone(HERE) datetime.datetime(2010, 12, 30, 15, 51, 22, 114668, tzinfo=tzlocal())

O bien, puedes hacerlo sin pytz o dateutil implementando tus propias zonas horarias. Pero eso sería una tontería.


No puedes hacerlo con la biblioteca estándar. Usando el módulo de pytz puedes convertir cualquier objeto de fecha / hora ingenuo / consciente a cualquier otra zona horaria. Veamos algunos ejemplos usando Python 3.

Objetos ingenuos creados a través del método de clase utcnow()

Para convertir un objeto ingenuo en cualquier otra zona horaria, primero debe convertirlo en un objeto datetime consciente . Puede usar el método de replace para convertir un objeto datetime ingenuo a un objeto datetime consciente . Luego, para convertir un objeto datetime consciente en cualquier otra zona horaria, puede usar el método astimezone .

La variable pytz.all_timezones le proporciona la lista de todas las zonas horarias disponibles en el módulo de pytz.

import datetime,pytz dtobj1=datetime.datetime.utcnow() #utcnow class method print(dtobj1) dtobj3=dtobj1.replace(tzinfo=pytz.UTC) #replace method dtobj_hongkong=dtobj3.astimezone(pytz.timezone("Asia/Hong_Kong")) #astimezone method print(dtobj_hongkong)

Objetos ingenuos creados a través del método de clase now()

Porque now método devuelve la fecha y la hora actuales, por lo que primero debe tener en cuenta la zona horaria del objeto datetime. La función de localize convierte un objeto datetime ingenuo en un objeto datetime que reconoce la zona horaria. Luego puede usar el método astimezone para convertirlo en otra zona horaria.

dtobj2=datetime.datetime.now() mytimezone=pytz.timezone("Europe/Vienna") #my current timezone dtobj4=mytimezone.localize(dtobj2) #localize function dtobj_hongkong=dtobj4.astimezone(pytz.timezone("Asia/Hong_Kong")) #astimezone method print(dtobj_hongkong)


Una forma simple (pero quizás defectuosa) que funciona en Python 2 y 3:

import time import datetime def utc_to_local(dt): return dt - datetime.timedelta(seconds = time.timezone)

Su ventaja es que es trivial escribir una función inversa