change - Python: Calcula la zona horaria local
set timezone to datetime python (13)
para comparar las marcas de tiempo UTC de un archivo de registro con marcas de tiempo locales.
Es difícil encontrar el nombre de Olson TZ para una zona horaria local de una manera portátil. Afortunadamente, no lo necesita para realizar la comparación.
tzlocal
módulo tzlocal
devuelve una zona horaria pytz correspondiente a la zona horaria local:
from datetime import datetime
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone()
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc) #NOTE: utc.normalize() is unnecessary here
A diferencia de otras soluciones presentadas hasta ahora, el código anterior evita los siguientes problemas:
- la hora local puede ser ambigua , es decir, una comparación precisa podría ser imposible para algunos momentos locales
- utc offset puede ser diferente para el mismo nombre de zona horaria local para las fechas del pasado. Algunas bibliotecas que admiten objetos datetime con
dateutil
zona horaria (p. Ej.,dateutil
) no lo tienen en cuenta
Nota: para obtener el objeto datetime compatible con la zona horaria de un objeto datetime ingenuo, debe usar * :
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
en lugar de:
#XXX fails for some timezones
local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz)
* is_dst=None
fuerza una excepción si la hora local dada es ambigua o inexistente.
Si está seguro de que todas las marcas de tiempo locales usan el mismo desplazamiento de utc (actual) para la zona horaria local, entonces podría realizar la comparación utilizando solo stdlib:
# convert a naive datetime object that represents time in local timezone to epoch time
timestamp1 = (datetime(2010, 4, 27, 12, 0, 0, 0) - datetime.fromtimestamp(0)).total_seconds()
# convert a naive datetime object that represents time in UTC to epoch time
timestamp2 = (datetime(2010, 4, 27, 9, 0) - datetime.utcfromtimestamp(0)).total_seconds()
timestamp1
y timestamp2
se pueden comparar directamente.
Nota:
-
timestamp1
fórmulatimestamp1
funciona solo si el desplazamiento UTC en época (datetime.fromtimestamp(0)
) es el mismo que ahora -
fromtimestamp()
crea un objeto naive datetime en la zona horaria local actual -
utcfromtimestamp()
crea un objeto naive datetime en UTC.
Quiero comparar las marcas de tiempo UTC de un archivo de registro con marcas de tiempo locales. Al crear el objeto local de datetime
, utilizo algo como:
>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
tzinfo=pytz.timezone(''Israel''))
Quiero encontrar una herramienta automática que reemplace el tzinfo=pytz.timezone(''Israel'')
con la zona horaria local actual.
¿Algunas ideas?
Aquí hay una versión un poco más concisa de la solución de @ vbem:
from datetime import datetime as dt
dt.utcnow().astimezone().tzinfo
La única diferencia sustancial es que reemplacé datetime.datetime.now(datetime.timezone.utc)
con datetime.datetime.utcnow()
. Para abreviar, también di alias datetime.datetime
como dt
.
Para mis propósitos, quiero el desplazamiento UTC en segundos. Esto es lo que parece:
dt.utcnow().astimezone().utcoffset().total_seconds()
En Python 3.x, la zona horaria local puede averiguarse así:
import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
Es un uso complicado del code de datetime
y datetime
.
En función de la respuesta anterior de Thoku, aquí hay una respuesta que resuelve la zona horaria a la media hora más cercana (que es relevante para algunas zonas horarias, por ejemplo, en Australia del Sur):
from datetime import datetime
round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2)
En primer lugar, tenga en cuenta que la pregunta presenta una inicialización incorrecta de un objeto datetime consciente:
>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
... tzinfo=pytz.timezone(''Israel''))
crea una instancia inválida Uno puede ver el problema calculando el desplazamiento UTC del objeto resultante:
>>> print(local_time.utcoffset())
2:21:00
(Tenga en cuenta el resultado que es una fracción impar de una hora).
Para inicializar un datetime con conocimiento utilizando pytz uno debe usar el método localize()
siguiente manera:
>>> local_time=pytz.timezone(''Israel'').localize(datetime.datetime(2010, 4, 27, 12))
>>> print(local_time.utcoffset())
3:00:00
Ahora, si necesita una zona horaria pytz local como el nuevo tzinfo, debe usar el paquete tzlocal como otros han explicado, pero si todo lo que necesita es una instancia con un desplazamiento y abreviación de zona horaria local correctos y luego con Python 3.3, puede llame al método astimezone()
sin argumentos para convertir una instancia de datetime
conocida en su zona horaria local:
>>> local_time.astimezone().strftime(''%Y-%m-%d %H:%M %Z %z'')
''2010-04-27 05:00 EDT -0400''
Esta es una forma de obtener la zona horaria local utilizando solo la biblioteca estándar (solo funciona en un entorno * nix):
>>> ''/''.join(os.path.realpath(''/etc/localtime'').split(''/'')[-2:])
''Australia/Sydney''
Puede usar esto para crear una pytz
horaria de pytz
:
>>> import pytz
>>> my_tz_name = ''/''.join(os.path.realpath(''/etc/localtime'').split(''/'')[-2:])
>>> my_tz = pytz.timezone(my_tz_name)
>>> my_tz
<DstTzInfo ''Australia/Sydney'' LMT+10:05:00 STD>
... que luego puede aplicar a una datetime
y datetime
:
>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059)
>>> now.replace(tzinfo=my_tz)
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059, tzinfo=<DstTzInfo ''Australia/Sydney'' LMT+10:05:00 STD>)
Evitar el módulo no estándar (parece ser un método que falta del módulo datetime):
from datetime import datetime
utcOffset_min = int(round((datetime.now() - datetime.utcnow()).total_seconds())) / 60 # round for taking time twice
utcOffset_h = utcOffset_min / 60
assert(utcOffset_min == utcOffset_h * 60) # we do not handle 1/2 h timezone offsets
print ''Local time offset is %i h to UTC.'' % (utcOffset_h)
Me estaba preguntando lo mismo a mí mismo, y encontré la respuesta en 1:
Eche un vistazo a la sección 8.1.7: el formato "% z" (minúscula, la mayúscula Z también devuelve la zona horaria, pero no en el formato de 4 dígitos, sino en forma de abreviaturas de zona horaria, como en [3]) of strftime devuelve el formulario "+/- 4DIGIT" que es estándar en los encabezados de correo electrónico (consulte la sección 3.3 de RFC 2822, consulte [2], que obsoleta las otras formas de especificar la zona horaria para los encabezados de correo electrónico).
Entonces, si quieres tu zona horaria en este formato, usa:
time.strftime("%z")
[1] http://docs.python.org/2/library/datetime.html
[2] http://tools.ietf.org/html/rfc2822#section-3.3
[3] Abreviaturas de zona horaria: http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations , solo para referencia.
Para cosas simples, se puede usar la siguiente implementación de tzinfo
, que consulta el sistema operativo para las compensaciones de zona horaria:
import datetime
import time
class LocalTZ(datetime.tzinfo):
_unixEpochOrdinal = datetime.datetime.utcfromtimestamp(0).toordinal()
def dst(self, dt):
return datetime.timedelta(0)
def utcoffset(self, dt):
t = (dt.toordinal() - self._unixEpochOrdinal)*86400 + dt.hour*3600 + dt.minute*60 + dt.second + time.timezone
utc = datetime.datetime(*time.gmtime(t)[:6])
local = datetime.datetime(*time.localtime(t)[:6])
return local - utc
print datetime.datetime.now(LocalTZ())
print datetime.datetime(2010, 4, 27, 12, 0, 0, tzinfo=LocalTZ())
# If you''re in the EU, the following datetimes are right on the DST change.
print datetime.datetime(2013, 3, 31, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 59, 59, tzinfo=LocalTZ())
# The following datetime is invalid, as the clock moves directly from
# 01:59:59 standard time to 03:00:00 daylight savings time.
print datetime.datetime(2013, 3, 31, 2, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 59, 59, tzinfo=LocalTZ())
# The following datetime is ambigous, as 02:00 can be either DST or standard
# time. (It is interpreted as standard time.)
print datetime.datetime(2013, 10, 27, 2, 0, 0, tzinfo=LocalTZ())
Primero obtener los módulos pytz y tzlocal
pip install pytz tzlocal
entonces
from tzlocal import get_localzone
local = get_localzone()
entonces puedes hacer cosas como
from datetime import datetime
print(datetime.now(local))
Según la respuesta de JF Sebastian , puede hacer esto con la biblioteca estándar:
import time, datetime
local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone))
Probado en 3.4, debería funcionar en 3.4+
El ejemplo del código sigue. Última cadena adecuada para usar en nombres de archivos.
>>> from datetime import datetime
>>> from dateutil.tz import tzlocal
>>> str(datetime.now(tzlocal()))
''2015-04-01 11:19:47.980883-07:00''
>>> str(datetime.now(tzlocal())).replace('' '',''-'').replace('':'','''').replace(''.'',''-'')
''2015-04-01-111947-981879-0700''
>>>