Solución:
En Python 3.3+:
from datetime import datetime, 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)
Utilizando 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()))
Producción
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 de MSK.
No sé si las soluciones que no son de Pytz funcionan en Windows.
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, puede hacerlo sin pytz o dateutil implementando sus propias zonas horarias. Pero eso sería una tontería.
No puede hacerlo con la biblioteca estándar. Utilizando Pytz módulo puede convertir cualquier objeto de fecha y 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 ingenuo objeto a cualquier otra zona horaria, primero tienes que convertirlo en consciente objeto de fecha y hora. Puedes usar el replace
método para convertir un ingenuo objeto de fecha y hora a un consciente objeto de fecha y hora. Luego, para convertir un consciente objeto de fecha y hora a cualquier otra zona horaria que pueda usar astimezone
método.
La variable pytz.all_timezones
le da la lista de todas las zonas horarias disponibles en el módulo 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
El método devuelve la fecha y hora actuales, por lo que primero debe hacer que el objeto datetime sea consciente de la zona horaria. los localize
función convierte un ingenuo objeto de fecha y hora en un objeto de fecha y hora compatible con la zona horaria. Entonces puedes usar el astimezone
método 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)