¿Cómo obtener la configuración de zona horaria del sistema y pasarla a pytz.timezone?

Podemos usar time.tzname obtener un nombre de zona horaria local, pero ese nombre no es compatible con pytz.timezone .

De hecho, el nombre devuelto por time.tzname es ambiguo. Este método devuelve ('CST', 'CST') en mi sistema, pero ‘CST’ puede indicar cuatro zonas horarias:

  • Zona horaria central (América del Norte): observada en la zona horaria central de América del Norte
  • Hora estándar de China
  • Hora estándar de Chungyuan: el término “Hora estándar de Chungyuan” ahora rara vez se usa en Taiwán
  • Hora estándar central de Australia (ACST)

tzlocal módulo tzlocal devuelve el objeto pytz tzinfo correspondiente a la zona horaria local:

 import time from datetime import datetime import pytz # $ pip install pytz from tzlocal import get_localzone # $ pip install tzlocal # get local timezone local_tz = get_localzone() # test it # utc_now, now = datetime.utcnow(), datetime.now() ts = time.time() utc_now, now = datetime.utcfromtimestamp(ts), datetime.fromtimestamp(ts) local_now = utc_now.replace(tzinfo=pytz.utc).astimezone(local_tz) # utc -> local assert local_now.replace(tzinfo=None) == now 

Funciona incluso durante las transiciones del horario de verano, cuando la hora local puede ser ambigua.

local_tz también funciona para fechas pasadas, incluso si el desplazamiento de utc para la zona horaria local era diferente en ese momento. dateutil.tz.tzlocal() solución basada en dateutil.tz.tzlocal() falla en este caso, por ejemplo, en la zona horaria de Europa / Moscú (ejemplo de 2013):

 >>> import os, time >>> os.environ['TZ'] = 'Europe/Moscow' >>> time.tzset() >>> from datetime import datetime >>> from dateutil.tz import tzlocal >>> from tzlocal import get_localzone >>> dateutil_tz = tzlocal() >>> tzlocal_tz = get_localzone() >>> datetime.fromtimestamp(0, dateutil_tz) datetime.datetime(1970, 1, 1, 4, 0, tzinfo=tzlocal()) >>> datetime.fromtimestamp(0, tzlocal_tz) datetime.datetime(1970, 1, 1, 3, 0, tzinfo=) 

dateutil devuelve un error UTC + 4 incorrecto en lugar del UTC + 3 correcto en 1970-01-01.

Para aquellos que chocaron con esto en 2017 dateutil.tz.tzlocal() todavía está roto. El ejemplo anterior funciona ahora porque la compensación de utf actual es UTC + 3 en Moscú (que por accidente es igual a la compensación de utc de 1970). Para demostrar el error, podemos elegir una fecha en la que la compensación utc sea UTC + 4:

 >>> import os, time >>> os.environ['TZ'] = 'Europe/Moscow' >>> time.tzset() >>> from datetime import datetime >>> from dateutil.tz import tzlocal >>> from tzlocal import get_localzone >>> dateutil_tz = tzlocal() >>> tzlocal_tz = get_localzone() >>> ts = datetime(2014, 6,1).timestamp() # get date in 2014 when gmtoff=14400 in Moscow >>> datetime.fromtimestamp(ts, dateutil_tz) datetime.datetime(2014, 5, 31, 23, 0, tzinfo=tzlocal()) >>> datetime.fromtimestamp(ts, tzlocal_tz) datetime.datetime(2014, 6, 1, 0, 0, tzinfo=) 

dateutil devuelve una compensación UTC + 3 incorrecta en lugar de la UTC + 4 correcta en 2014-06-01.

Use la función python-dateutil paquete python-dateutil :

 from dateutil.tz import tzlocal localtimezone = tzlocal() 

Internamente, esta es una clase que usa time.timezone y time.altzone (cambio basado en time.daylight ), pero crea un objeto de zona horaria adecuado a partir de eso.

pytz esto en lugar de una pytz horaria de pytz .

La alternativa es leer la zona horaria actualmente configurada desde el sistema operativo, pero esto difiere ampliamente de un sistema operativo a otro. En Mac OS X debe leer la salida de systemsetup -gettimezone :

 $ systemsetup -gettimezone Time Zone: Europe/Copenhagen 

En los sistemas Debian y Ubuntu, puede leer /etc/timezone :

 $ cat /etc/timezone Europe/Oslo 

En los sistemas RedHat y direved, deberá leerlo desde /etc/sysconfig/clock :

 $ grep ZONE /etc/sysconfig/clock ZONE="Europe/Oslo" 

Un método muy simple para resolver esta pregunta:

 import time def localTzname(): offsetHour = time.timezone / 3600 return 'Etc/GMT%+d' % offsetHour 

Actualización : @MartijnPieters dijo ‘Esto no funcionará con el horario de verano / hora de verano’. Entonces, ¿qué hay de esta versión?

 import time def localTzname(): if time.daylight: offsetHour = time.altzone / 3600 else: offsetHour = time.timezone / 3600 return 'Etc/GMT%+d' % offsetHour 

Desde Python 3.6, simplemente puede ejecutar naive_datetime.astimezone() y la zona horaria del sistema se agregará al objeto naive_datetime .

Si se llama sin argumentos (o con tz = Ninguno), la zona horaria local del sistema se supone para la zona horaria de destino. El atributo .tzinfo de la instancia de fecha y hora convertida se establecerá en una instancia de zona horaria con el nombre de la zona y el desplazamiento obtenido del sistema operativo.

https://docs.python.org/3/library/datetime.html#datetime.datetime.astimezone

Ejemplo:

 >>> import datetime >>> datetime.datetime.now().astimezone().isoformat(timespec='minutes') '2018-10-02T13:09+03:00' 

No sé si esto es útil para usted o no, pero creo que responde a su problema más general:

Si tiene una fecha que se encuentra en una zona horaria ambigua, como CST , simple-date (solo python 3.2+, lo siento) puede automatizar la búsqueda y le permite hacer cosas como preferir ciertos países.

por ejemplo:

 >>> SimpleDate('2013-07-04 18:53 CST') Traceback [... simpledate.AmbiguousTimezone: 3 distinct timezones found: ; ;  (timezones=('CST',), datetime=datetime.datetime(2013, 7, 4, 18, 53), is_dst=False, country=None, unsafe=False) >>> SimpleDate('2013-07-04 18:53 CST', country='CN') SimpleDate('2013-07-04 18:53 CST') >>> SimpleDate('2013-07-04 18:53 CST', country='CN').utc SimpleDate('2013-07-04 10:53 UTC', tz='UTC') 

observe cómo, al especificar un país, reduce el rango de valores posibles lo suficiente como para permitir la conversión a UTC.

se implementa haciendo una búsqueda en las zonas horarias en PyTZ:

 >>> SimpleDate('2013-07-04 18:53 CST', country='CN', debug=True) ... PyTzFactory: Have country code CN PyTzFactory: Country code CN has 5 timezones PyTzFactory: Expanded country codes to 5 timezones PyTzFactory: Expanding ('CST',) PyTzFactory: Name lookup failed for CST PyTzFactory: Found CST using Asia/Shanghai PyTzFactory: Found CST using Asia/Harbin PyTzFactory: Found CST using Asia/Chongqing PyTzFactory: Found CST using Asia/Urumqi PyTzFactory: Found CST using Asia/Kashgar PyTzFactory: Expanded timezone to 5 timezones PyTzFactory: New offset 8:00:00 for Asia/Shanghai PyTzFactory: Known offset 8:00:00 for Asia/Harbin PyTzFactory: Known offset 8:00:00 for Asia/Chongqing PyTzFactory: Known offset 8:00:00 for Asia/Urumqi PyTzFactory: Known offset 8:00:00 for Asia/Kashgar PyTzFactory: Have 1 distinct timezone(s) PyTzFactory: Found Asia/Shanghai ... SimpleDate('2013-07-04 18:53 CST') 

Finalmente, para responder directamente a la pregunta, también se ajusta a tzlocal, como se menciona en otra respuesta aquí, por lo que automáticamente hará lo que espera si no da una zona horaria. por ejemplo, vivo en chile, asi que

 >>> SimpleDate() SimpleDate('2013-07-04 19:21:25.757222 CLT', tz='America/Santiago') >>> SimpleDate().tzinfo  

da la zona horaria de mi localidad (ambigua o no).

 import pytz 

digamos que tiene una lista de valores utc DateTime en el objeto de la lista OBJ.

 tz=pytz.timezone('Asia/Singapore') 

encuentre debajo de la url para obtener el parámetro de cadena posicional respectivo de la zona horaria ¿Hay una lista de zonas horarias de Pytz?

Ahora nuestro tz es objeto teniendo Singapur Time

 result=[] for i in OBJ: i=i+tz.utcoffset(i) result.append(i) 

el objeto de la lista de resultados tiene el valor DateTime de su respectiva zona horaria