time.tzname
permet d’obtenir un nom de fuseau horaire local, mais ce nom n’est pas compatible avec pytz.timezone
.
En fait, le nom renvoyé par time.tzname
est ambigu. Cette méthode renvoie ('CST', 'CST')
dans mon système, mais 'CST' peut indiquer quatre fuseaux horaires:
Une méthode très simple pour résoudre cette question:
import time
def localTzname():
offsetHour = time.timezone / 3600
return 'Etc/GMT%+d' % offsetHour
Mise à jour : @MartijnPieters a déclaré: «Cela ne fonctionnera pas avec l'heure d'été/heure d'été. Alors, qu'en est-il de cette version?
import time
def localTzname():
if time.daylight:
offsetHour = time.altzone / 3600
else:
offsetHour = time.timezone / 3600
return 'Etc/GMT%+d' % offsetHour
tzlocal
module retourne l'objet de pytz tzinfo correspondant au fuseau horaire 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
Il fonctionne même pendant les transitions à l'heure avancée lorsque l'heure locale peut être ambiguë.
local_tz
fonctionne également pour les dates antérieures même si le décalage utc pour le fuseau horaire local était différent à l'époque. La solution basée sur dateutil.tz.tzlocal()
- échoue dans ce cas, par exemple, dans le fuseau horaire Europe/Moscou (exemple à partir 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=<DstTzInfo 'Europe/Moscow' MSK+3:00:00 STD>)
dateutil renvoie le décalage faux UTC + 4 au lieu du UTC + 3 correct le 1970-01-01.
_ {Pour ceux qui se heurtent à cela en 2017} _ dateutil.tz.tzlocal()
est toujours cassé. L'exemple ci-dessus fonctionne maintenant car l'offset utf actuel est UTC + 3 à Moscou (accidentellement égal à l'offset utc de 1970). Pour démontrer l'erreur, nous pouvons choisir une date à laquelle utc offset est 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=<DstTzInfo 'Europe/Moscow' MSK+4:00:00 STD>)
dateutil renvoie faux décalage UTC + 3 au lieu du correct UTC + 4 le 2014-06-01.
Utilisez la fonction tzlocal
du paquet python-dateutil
:
from dateutil.tz import tzlocal
localtimezone = tzlocal()
En interne, il s'agit d'une classe qui utilise time.timezone
et time.altzone
(commutation basée sur time.daylight
), mais crée un objet fuseau horaire approprié à partir de cela.
Vous utilisez ce à la place d'un fuseau horaire pytz
.
L'alternative consiste à lire le fuseau horaire actuellement configuré à partir du système d'exploitation, mais cela diffère grandement d'un système d'exploitation à l'autre. Sous Mac OS X, vous devez lire le résultat de systemsetup -gettimezone
:
$ systemsetup -gettimezone
Time Zone: Europe/Copenhagen
Sur les systèmes Debian et Ubuntu, vous pouvez lire /etc/timezone
:
$ cat /etc/timezone
Europe/Oslo
Sur les systèmes RedHat et direved, vous devrez le lire à partir de /etc/sysconfig/clock
:
$ grep ZONE /etc/sysconfig/clock
ZONE="Europe/Oslo"
Depuis Python 3.6, vous pouvez simplement exécuter naive_datetime.astimezone()
et le fuseau horaire du système sera ajouté à l’objet naive_datetime
.
Si appelé sans arguments (ou avec tz = None), le fuseau horaire local du système est supposé pour le fuseau horaire cible. L'attribut .tzinfo de l'instance datetime convertie sera défini sur une instance de fuseau horaire avec le nom de la zone et le décalage obtenus à partir du système d'exploitation.
https://docs.python.org/3/library/datetime.html#datetime.datetime.astimezone
Exemple:
>>> import datetime
>>> datetime.datetime.now().astimezone().isoformat(timespec='minutes')
'2018-10-02T13:09+03:00'
je ne sais pas si cela vous est utile ou non, mais je pense que cela répond à votre problème plus général:
si vous avez une date qui se trouve dans un fuseau horaire ambigu, comme CST
, simple-date (désolé python 3.2+ seulement), vous pouvez automatiser la recherche et vous permettre de faire des choses comme préférer certains pays.
par exemple:
>>> SimpleDate('2013-07-04 18:53 CST')
Traceback [...
simpledate.AmbiguousTimezone: 3 distinct timezones found: <DstTzInfo 'Australia/Broken_Hill' CST+9:30:00 STD>; <DstTzInfo 'America/Regina' LMT-1 day, 17:01:00 STD>; <DstTzInfo 'Asia/Harbin' LMT+8:27:00 STD> (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')
remarquez comment, en spécifiant un pays, vous réduisez suffisamment la plage de valeurs possibles pour permettre la conversion en UTC.
il est implémenté en faisant une recherche sur les fuseaux horaires dans 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')
enfin, pour répondre directement à la question posée, tzlocal est également enveloppé, comme indiqué dans une autre réponse, et fera automatiquement ce que vous attendez si vous ne définissez pas de fuseau horaire. par exemple, je vis au Chili, donc
>>> SimpleDate()
SimpleDate('2013-07-04 19:21:25.757222 CLT', tz='America/Santiago')
>>> SimpleDate().tzinfo
<DstTzInfo 'America/Santiago' CLT-1 day, 20:00:00 STD>
donne le fuseau horaire de mes paramètres régionaux (ambigu ou non).