Gestion des fuseaux horaires en Python (datetime, pytz)

J'ai eu du mal à comprendre comment gérer les fuseaux horaires en Python, il s'agit donc d'un mémo organisé.

information sur la version

classe datetime

Il existe les deux types d'instances suivants dans la même classe.

Aware and Naive Objects - datetime — Basic date and time types — Python 3.8.1rc1 documentation

Comment obtenir l'heure actuelle

from datetime import datetime
from datetime import timezone

now = datetime.now()
print(now) # =>Maintenant au Japon temps
print(now.tzinfo) # => None
# Naive

now = datetime.utcnow()
print(now) # =>Heure moins 9 heures à partir de l'heure du Japon
print(now.tzinfo) # => None
# Naive

now = datetime.now(timezone.utc)
print(now) #À l'époque moins 9 heures"+00:00"Avec la notation
print(now.tzinfo) # => UTC
# Aware

Comment obtenir une instance de datetime à partir d'Unixtime

from datetime import datetime
from datetime import timezone

unixtime = 1572764400

now = datetime.fromtimestamp(unixtime)
print(now) # =>Notation en japonais de l'heure du moment représentée par l'heure unix
print(now.tzinfo) # => None
# Naive

now = datetime.utcfromtimestamp(unixtime)
print(now) #Temps moins 9 heures=Notation en UTC au moment représenté par l'heure unix
print(now.tzinfo) # => None
# Naive

now = datetime.fromtimestamp(unixtime, timezone.utc)
print(now) #À l'époque moins 9 heures"+00:00"Avec la notation
print(now.tzinfo)
# => UTC
# Aware

Un moyen rapide de passer 9 heures sans dire des choses difficiles

from datetime import datetime
from datetime import timedelta

now = datetime.now() # Naive
print(now) # =>Maintenant au Japon temps(Aucune information sur le fuseau horaire)
print(now - timedelta(hours = +9)) # =>Temps moins 9 heures(Aucune information sur le fuseau horaire)

now = datetime.utcnow() # Naive
print(now) # =>J'ai tiré 9 heures maintenant(Aucune information sur le fuseau horaire)
print(now + timedelta(hours = +9)) # =>9 heures supplémentaires de l'heure du Japon(Aucune information sur le fuseau horaire)

Classe représentant le fuseau horaire

classe tzinfo

tzinfo est une classe abstraite avec les informations suivantes.

--Nom de la zone horaire --Valeur de décalage horaire à partir de UTC --Valeur de décalage horaire à partir de UTC en heure d'été

tzinfo - datetime — Basic date and time types — Python 3.8.1rc1 documentation

Utilisez timezone ou pytz comme classe concrète. pytz n'est pas dans la bibliothèque standard et doit être installé.

classe de fuseau horaire

timezone est une classe concrète de tzinfo avec une valeur de décalage fixe. Il est fixe et peut être utilisé comme fuseau horaire tel que +09: 00, mais on ne peut pas considérer que la valeur de décalage change en fonction de la date et de l'heure, comme l'heure d'été.

paquet pytz

Le paquet pytz vous permet de générer une classe concrète de tzinfo à partir d'une chaîne comme" "Asia / Tokyo" ". On peut considérer que la valeur de décalage avec UTC change en fonction de la date et de l'heure.

Exemple où la valeur de décalage change en fonction de la date et de l'heure

pytz n'est pas une bibliothèque standard et doit être installé.

$ pip install pytz

Exemple

classe de fuseau horaire

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import pytz

dt = datetime.utcfromtimestamp(1572764400)
print(dt)
# => 2019-11-03 07:00:00
#1572764400 est 16:00 le 3ème heure du Japon

# timezone.utc a 0 valeur de décalage, pas d'heure d'été
utc = timezone.utc
print(utc.utcoffset(dt))
# => 0:00:00
print(utc.dst(dt))
# => None

#Instance de la classe de fuseau horaire
tz8 = timezone(timedelta(hours=-8)) #Fuseau horaire représentant 8 heures de retard sur UTC
print(tz8.utcoffset(dt))
# => -1 day, 16:00:00
print(tz8.dst(dt))
# => None

#L'heure du Japon a une valeur de décalage+9 heures sans heure d'été
tokyo = pytz.timezone('Asia/Tokyo') #Heure du Japon
print(tokyo.utcoffset(dt))
# => 9:00:00
print(tokyo.dst(dt))
# => 0:00:00

#À 7 h 00 le 3 novembre à UTC, la valeur de décalage correspond à l'heure du Pacifique américain.-8 heures n'est pas l'heure d'été
lasvegas = pytz.timezone('America/Los_Angeles') #Heure du Pacifique américain
print(lasvegas.utcoffset(dt))
# => -1 day, 16:00:00
print(lasvegas.dst(dt))
# => 0:00:00

#La veille, la valeur de décalage était en heure du Pacifique américain-7 heures est l'heure d'été
print(lasvegas.utcoffset(dt - timedelta(days = 1)))
# => -1 day, 17:00:00
print(lasvegas.dst(dt - timedelta(days = 1)))
# => 1:00:00

conversion de fuseau horaire datetime

Si vous utilisez le fuseau horaire pour une instance datetime Naive sans informations de fuseau horaire, il sera converti du fuseau horaire de l'environnement local au fuseau horaire spécifié. Après la conversion, il devient une instance Aware.

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import pytz

dt = datetime.utcfromtimestamp(1572764400)
print(dt)
# => 2019-11-03 07:00:00
#1572764400 est 16:00 le 3ème heure du Japon

#dt est une instance créée par UTC à 7 heures le 3,
#Parce qu'il s'agit d'une instance Naive sans informations de fuseau horaire
#Il sera converti au fuseau horaire spécifié à 7 heures le 3ème heure du Japon.

tokyo = pytz.timezone('Asia/Tokyo') #Heure du Japon
print(dt.astimezone(tokyo))
# => 2019-11-03 07:00:00+09:00
#Étant donné que l'environnement PC local est l'heure du Japon, l'heure ne change pas

lasvegas = pytz.timezone('America/Los_Angeles') #Heure du Pacifique américain
print(dt.astimezone(lasvegas))
# => 2019-11-02 15:00:00-07:00
#7h00 le 3 novembre, l'heure du Japon a 16 heures de retard sur le Japon en heure d'été par rapport à l'heure du Pacifique des États-Unis

tz8 = timezone(timedelta(hours=-8)) #Fuseau horaire représentant 8 heures de retard sur UTC
print(dt.astimezone(tz8))
# => 2019-11-02 14:00:00-08:00

Si vous utilisez le fuseau horaire pour une instance datetime Aware avec des informations de fuseau horaire, le fuseau horaire d'origine sera converti dans le fuseau horaire spécifié. Il restera une instance Aware après la conversion.

# dt.replace(tzinfo=utc)Seules les informations de fuseau horaire sont ajoutées sans modifier les valeurs de l'année, du mois, du jour, de l'heure, des minutes et des secondes.

print(dt.replace(tzinfo=utc).astimezone(tokyo))
# => 2019-11-03 16:00:00+09:00
print(dt.replace(tzinfo=utc).astimezone(lasvegas))
# => 2019-11-03 00:00:00-07:00
print(dt.replace(tzinfo=utc).astimezone(tz8))
# => 2019-11-02 23:00:00-08:00

Jetons un coup d'œil à la conversion de l'heure UTC à l'heure du Pacifique américain à la fin de l'heure d'été.

from datetime import datetime
import pytz

lasvegas = pytz.timezone('America/Los_Angeles') #Heure du Pacifique américain

for i in range(7):
    dt = datetime.utcfromtimestamp(1572764400 + i * 1800)
    #1572764400 est UTC à 7 heures le 3
    print(dt.replace(tzinfo=utc).astimezone(lasvegas))
# =>
# 2019-11-03 00:00:00-07:00
# 2019-11-03 00:30:00-07:00
# 2019-11-03 01:00:00-07:00
# 2019-11-03 01:30:00-07:00
# 2019-11-03 01:00:00-08:00 <-Le temps remonte à la fin de l'heure d'été
# 2019-11-03 01:30:00-08:00
# 2019-11-03 02:00:00-08:00

19 minutes de problème

Si vous utilisez dt.replace (tzinfo = tokyo) ou datetime (2019, 11, 3, 1, 0, 0, tzinfo = tokyo) dans l'objet de fuseau horaire généré à partir de pytz, 19 Il y a un problème qui peut être compris. Il est de 19 minutes au Japon, mais 7 minutes en Amérique Pacifique.

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import pytz

dt = datetime.utcfromtimestamp(1572742800)
print(dt)
# => 2019-11-03 01:00:00
#1572764400 est 1:00 le 3ème heure du Japon

utc = timezone.utc
print(dt.replace(tzinfo=utc))
# => 2019-11-03 01:00:00+00:00

Si vous définissez replace (tzinfo = utc) sur une instance de datetime Naive, elle deviendra une instance Aware avec les informations +00: 00. Si vous spécifiez l'heure japonaise au lieu de ʻutc`,

tokyo = pytz.timezone('Asia/Tokyo') #Heure du Japon
print(dt.replace(tzinfo=tokyo))
# => 2019-11-03 01:00:00+09:19

Pour une raison quelconque, le décalage horaire est décalé de 19 minutes.

Il n'y a pas de problème si vous utilisez la méthode localize. Je ne sais pas ce qui est différent.

print(tokyo.localize(dt))
# => 2019-11-03 01:00:00+09:00

Même si vous l'essayez à l'heure du Pacifique américain, la largeur de l'écart est différente, mais elle ne change pas.

lasvegas = pytz.timezone('America/Los_Angeles') #Heure du Pacifique américain

print(dt.replace(tzinfo=lasvegas))
# => 2019-11-03 01:00:00-07:53

print(lasvegas.localize(dt))
# => 2019-11-03 01:00:00-08:00

Comportement à la fin de l'heure d'été

Le troisième jour de l'heure du Pacifique américain est le jour de la fin de l'heure d'été et, comme illustré dans l'exemple ci-dessus, lorsque l'heure est indiquée toutes les 30 minutes, l'heure s'écoule comme suit.

2019-11-03 00:00:00-07:00 2019-11-03 00:30:00-07:00 2019-11-03 01:00:00-07:00 2019-11-03 01:30:00-07:00 2019-11-03 01: 00: 00-08: 00 <-L'heure revient à la fin de l'heure d'été 2019-11-03 01:30:00-08:00 2019-11-03 02:00:00-08:00

Il tourne deux fois de 1 h à 1 h 59. En d'autres termes, il existe une ambiguïté selon laquelle il n'est pas possible de dire si c'est la première ou la deuxième fois à partir de l'information de 1 heure.

Sur la base de ce fait, essayez localiser.

from datetime import datetime
from datetime import timedelta
from datetime import timezone
import pytz

dt = datetime.utcfromtimestamp(1572742800)
print(dt)
# => 2019-11-03 01:00:00
#dt est une instance naïve à 1 heure le 3

lasvegas = pytz.timezone('America/Los_Angeles') #Heure du Pacifique américain

print(lasvegas.localize(dt))
# => 2019-11-03 01:00:00-08:00
#La seconde 1 heure est revenue

À propos, si vous calculez 1 heure avant 1 heure pour la deuxième fois, ce sera 0 heure. Ce devrait être l'heure d'été à minuit, mais cela reste l'heure d'hiver.

print(lasvegas.localize(dt) - timedelta(hours=1))
# => 2019-11-03 00:00:00-08:00

Si vous calculez il y a 1 heure pour l'instance Naive avant localize puis localize, il sera 0 heures en heure d'été. C'est 2 heures avant la seconde 1 heure.

print(lasvegas.localize(dt - timedelta(hours=1)))
# => 2019-11-03 00:00:00-07:00

c'est tout.

Recommended Posts

Gestion des fuseaux horaires en Python (datetime, pytz)
Manipulation de json en python
Comment gérer l'hexadécimal en Python3
Traitement des URL relatives en python
Gestion des fichiers JSON en Python
Conversion de la chaîne <-> date (date, datetime) en Python
Exemple de gestion des fichiers eml en Python
Importation de modules et gestion des exceptions en python
Quadtree en Python --2
CURL en Python
Métaprogrammation avec Python
Python 3.3 avec Anaconda
Géocodage en python
SendKeys en Python
Méta-analyse en Python
Unittest en Python
Discord en Python
DCI en Python
tri rapide en python
nCr en python
Gestion des erreurs Python
N-Gram en Python
Programmation avec Python
Gestion des exceptions Python
Plink en Python
Constante en Python
FizzBuzz en Python
Sqlite en Python
Étape AIC en Python
Gestion des fuseaux horaires Python
LINE-Bot [0] en Python
CSV en Python
Assemblage inversé avec Python
Réflexion en Python
Constante en Python
nCr en Python.
format en python
Scons en Python 3
Puyopuyo en python
python dans virtualenv
PPAP en Python
Quad-tree en Python
Réflexion en Python
Chimie avec Python
Hashable en Python
DirectLiNGAM en Python
LiNGAM en Python
Gestion des exceptions Python
Aplatir en Python
Aplatir en python
Créer un objet datetime à partir d'une chaîne en Python (Python 3.3)
Comportement lors de l'enregistrement d'un objet datetime python dans MongoDB
Comment gérer le type datetime dans sqlite3 de python
Liste triée en Python
AtCoder # 36 quotidien avec Python
Texte de cluster en Python
AtCoder # 2 tous les jours avec Python
Daily AtCoder # 32 en Python