example biblioteca python datetime timezone utc

biblioteca - strftime python



Python: dada la hora actual en UTC, ¿cómo se determina la hora de inicio y finalización del día en una zona horaria en particular? (4)

Creo que está obteniendo este resultado porque está agregando un día en lugar de 86400 segundos. No existe una equivalencia uniforme, siempre correcta entre días y segundos. Por ejemplo, si pytz fuerce un día a "realmente" ser 86400 segundos, entonces agregar un día a una fecha del 31 de diciembre o 30 de junio a veces hará que el campo de segundos del resultado esté "un segundo apagado", porque en algunos años esos días han tenido 86401 segundos. (Es posible que tengan 86402 o incluso 86399 segundos en el futuro).

Por lo tanto, agregar un día significa simplemente aumentar el día en uno, llevando a mes y año si es necesario, pero sin cambiar los campos de hora del día. Intente agregar 86400 segundos y vea si obtiene el resultado deseado.

Estoy jugando con Google App Engine y me enteré de que la zona horaria está fijada en UTC. Deseo determinar la hora de inicio y finalización del día actual para la zona horaria local del usuario. Básicamente, dada la hora actual en UTC, ¿cómo se determina la hora de inicio y finalización del día actual, teniendo en cuenta los cambios en el horario de verano?

Tengo un código de ejemplo torpe. Tenga en cuenta que me doy cuenta de que si estoy especificando manualmente una fecha, también podría especificar la fecha de mañana, pero son ejemplos y quiero determinarlo de forma programática. Mi problema principal es que si agrego un timedelta a un datetime con una zona horaria y luego lo normalizo (como se sugiere en los documentos de pytz) obtengo un datetime que es una hora libre durante los cambios de horario de verano.

No se menciona en el código, pero en última instancia, el objetivo es convertir estos tiempos a UTC, por lo que es importante ser consciente de la zona horaria.

#!/usr/bin/python import datetime from pytz.gae import pytz hobart_tz = pytz.timezone(''Australia/Hobart'') utc_dt = pytz.utc.localize(datetime.datetime.utcnow()) hobart_dt = utc_dt.astimezone(hobart_tz) # create a new datetime for the start of the day and add a day to it to get tomorrow. today_start = datetime.datetime(hobart_dt.year, hobart_dt.month, hobart_dt.day) today_start = hobart_tz.localize(today_start) today_end = hobart_tz.normalize(today_start + datetime.timedelta(days=1)) print ''today:'', today_start print '' next:'', today_end print # gives: # today: 2011-08-28 00:00:00+10:00 # next: 2011-08-29 00:00:00+10:00 # but say today is a daylight savings changeover. # after normalisation, we are off by an hour. dst_finish_2011 = datetime.datetime(2011, 4, 3) # this would come from hobart_dt dst_finish_2011 = hobart_tz.localize(dst_finish_2011) next = hobart_tz.normalize(dst_finish_2011 + datetime.timedelta(days=1)) print ''2011-04-03:'', dst_finish_2011 print ''2011-04-04:'', next # expect 2011-04-04 00:00:00+10:00 print # gives # 2011-04-03: 2011-04-03 00:00:00+11:00 # 2011-04-04: 2011-04-03 23:00:00+10:00 (wrong) dst_start_2011 = datetime.datetime(2011, 10, 2) # this would come from hobart_dt dst_start_2011 = hobart_tz.localize(dst_start_2011) next = hobart_tz.normalize(dst_start_2011 + datetime.timedelta(days=1)) print ''2011-10-02:'', dst_start_2011 print ''2011-10-03:'', next # expect 2011-10-03 00:00:00+11:00 print # gives # 2011-10-02: 2011-10-02 00:00:00+10:00 # 2011-10-03: 2011-10-03 01:00:00+11:00 (wrong) # I guess we could ignore the timezone and localise *after* ? dst_finish_2011 = datetime.datetime(2011, 4, 3) # this would come from hobart_dt next = dst_finish_2011 + datetime.timedelta(days=1) # now localise dst_finish_2011 = hobart_tz.localize(dst_finish_2011) next = hobart_tz.localize(next) print ''2011-04-03:'', dst_finish_2011 print ''2011-04-04:'', next # expect 2011-04-04 00:00:00+10:00 print # gives # 2011-04-03: 2011-04-03 00:00:00+11:00 # 2011-04-04: 2011-04-04 00:00:00+10:00


Después de un poco de experimentación y pensamiento, creo que tengo una solución para ti. Mi respuesta anterior no era correcta como usted señaló; un objeto timedelta para days = 1 es básicamente el mismo que para seconds = 86400 (excepto cuando se trata de segundos intercalares).

Una forma, como recomendaría, de incrementar la fecha sin tener en cuenta la hora del día es usar un objeto datetime.date lugar de un objeto datetime.datetime :

>>> oneday = datetime.timedelta(days=1) >>> d = datetime.date(2011,4,3) >>> str(d + oneday) ''2011-04-04''

La hora del día podría agregarse para formar un objeto datetime.datetime completo en el que sepa que los campos de la hora del día no se alteran con respecto a su valor original.

Otro método, uno que me sentiría seguro de usar, es trabajar temporalmente con fechas "ingenuas". De esta forma, no se aplicará una política de zona horaria al agregar el timedelta .

>>> hob = pytz.timezone(''Australia/Hobart'') >>> dstlast = datetime.datetime(2011,4,3) >>> str(dstlast) ''2011-04-03 00:00:00'' >>> dstlasthob = hob.localize(dstlast) >>> str(dstlasthob) ''2011-04-03 00:00:00+11:00'' >>> oneday = datetime.timedelta(days=1) >>> str(hob.normalize(dstlasthob + oneday)) ''2011-04-03 23:00:00+10:00'' >>> nextday = hob.localize(dstlasthob.replace(tzinfo=None) + oneday) >>> str(nextday) ''2011-04-04 00:00:00+10:00''

Probé este método para las fechas que tienen segundos intercalares (un ejemplo es 2008-12-31) y el resultado tiene la hora del día 00:00:00. Lo cual puede ser incorrecto, no estoy seguro, pero es lo que quieres :-)


El siguiente código intenta obtener una hora de medianoche; si el ajuste de zona horaria lo hace fallar, se reajusta a la medianoche con el nuevo desplazamiento de zona.

def DayStartEnd(localized_dt): tz = localized_dt.tzinfo start = tz.normalize(datetime.datetime(localized_dt.year,localized_dt.month,localized_dt.day,0,0,0,0,tz)) after_midnight = start.hour*60*60 + start.minute*60 + start.second if start.day != localized_dt.day: start += datetime.timedelta(seconds = 24*60*60 - after_midnight) elif after_midnight != 0: start -= datetime.timedelta(seconds = after_midnight) end = tz.normalize(start + datetime.timedelta(hours=24)) after_midnight = end.hour*60*60 + end.minute*60 + end.second if end.day == localized_dt.day: end += datetime.timedelta(seconds = 24*60*60 - after_midnight) elif after_midnight != 0: end -= datetime.timedelta(seconds = after_midnight) return start,end >>> hobart_tz = pytz.timezone(''Australia/Hobart'') >>> dst_finish_2011 = datetime.datetime(2011, 4, 3) >>> dst_finish_2011 = hobart_tz.localize(dst_finish_2011) >>> start,end = DayStartEnd(dst_finish_2011) >>> print start,end 2011-04-03 00:00:00+11:00 2011-04-04 00:00:00+10:00 >>> dst_start_2011 = datetime.datetime(2011, 10, 2) >>> dst_start_2011 = hobart_tz.localize(dst_start_2011) >>> start,end = DayStartEnd(dst_start_2011) >>> print start,end 2011-10-02 00:00:00+10:00 2011-10-03 00:00:00+11:00


Para saber la hora de inicio del día (medianoche) y la hora del final del día (mañana) en la zona horaria local, conociendo la hora UTC:

#!/usr/bin/env python from datetime import datetime, time, timedelta import pytz # $ pip install pytz from tzlocal import get_localzone # $ pip install tzlocal tz = get_localzone() # get the local timezone as pytz.timezone now = datetime.now(pytz.utc) # some UTC time dt = now.astimezone(tz) # the same time in the local timezone today = dt.date() # today in the local timezone (naive date object) midnight = datetime.combine(today, time()) # midnight in the local timezone aware_midnight = tz.localize(midnight, is_dst=None) # raise exception # for ambiguous or # non-existing # times tomorrow = midnight + timedelta(1) aware_tomorrow = tz.localize(tomorrow, is_dst=None) def print_time(aware_dt, fmt="%Y-%m-%d %H:%M:%S %Z%z"): print(aware_dt.strftime(fmt)) utc_dt = aware_dt.astimezone(pytz.utc) # the same time in UTC print(utc_dt.strftime(fmt)) print_time(aware_midnight) print_time(aware_tomorrow)

Salida

2014-09-01 00:00:00 EST+1000 2014-08-31 14:00:00 UTC+0000 2014-09-02 00:00:00 EST+1000 2014-09-01 14:00:00 UTC+0000

Ver también,

  • ¿Cómo obtengo la hora UTC de "medianoche" para una zona horaria determinada? - solo medianoche (no mañana)
  • ¿Cómo puedo restar un día de una fecha python? - sobre la diferencia entre hace un día y ayer
  • python - datetime con timezone to epoch - demuestra cuán fácil es producir una respuesta incorrecta (para algunas fechas, zonas horarias).