Ich habe ein kleines Tool geschrieben, das Informationen einschließlich der Zeit von einer externen API empfängt und Slack benachrichtigt, aber ich konnte die Zeitzone nicht konsistent und stabil konvertieren, was bedeutet. Notieren Sie sich, was Sie während der Umfrage gelernt haben und welche Lösungen möglich sind.
pytz.timezone.localize (datetime)
, wenn Sie pytz für die Zeitzonenkonvertierung verwenden.datetime.replace
nicht zu verwendenIn meinem Fall gab es verschiedene Arten von Stolpersteinen.
Abschließend zeige ich Ihnen, was ich über diese recherchiert habe und welchen Code ich geschrieben habe, um sie zu überwinden.
Timezeon aware / Offest native
Es gibt die beiden oben genannten Datums- / Uhrzeittypen.
Timezone Aware ist eine Datums- und Uhrzeitangabe mit einer explizit angegebenen Zeitzone, und Offset native ist eine Zeit ohne Angabe einer Zeitzone. Die beiden können nicht verglichen werden.
Diese müssen unterschieden werden.
import os
from datetime import datetime
import pytz
# Offest native
d1 = datetime.utcnow()
print(d1)
>>> 2020-04-19 10:07:47.885883
# Timezone aware
d2 = pytz.utc.localize(d1)
print(d2)
>>> 2020-04-19 10:07:47.885883+00:00
#Die beiden können nicht verglichen werden
d1 < d2
# >>> TypeError: can't compare offset-naive and offset-aware datetimes
Die Zeitzone scheint durch den Ort und die ** Zeit ** bestimmt zu sein. Es scheint einen Fall zu geben, in dem die Definition des Zeitunterschieds aufgrund historischer Umstände geändert wird, und unser Japan entspricht auch diesem Beispiel.
Es scheint, dass der Zeitunterschied zwischen Tokio bis 1888 und danach unterschiedlich ist, und vor 1888 scheint er ** + 09: 19 ** von UTC entfernt zu sein. Pytz berücksichtigt diese strikte Überlegung, und es scheint, dass dies bei einigen Methoden des Zeitzonenumwandlungssystems (datetime.replace usw.) berücksichtigt wird.
import pytz
#Hier ANZEIGE_TIMEZONE='Asia/Tokyo'Annehmen
DISPLAY_TIMEZONE = os.environ.get('DISPLAY_TIMEZONE')
tz = pytz.timezone(DISPLAY_TIMEZONE)
tz
>>> <DstTzInfo 'Asia/Tokyo' LMT+9:19:00 STD>
Es ist 19 Minuten weg. Dies scheint jedoch aufgrund der ordnungsgemäßen Einhaltung korrekt zu sein.
Wenn Ihr Programm ** Offset native ** behandelt, können Sie timezone.localize ()
verwenden, die vom Zeitzonenobjekt von pytz bereitgestellt wird. Es wird um +09: 00 richtig konvertiert.
** Solange Sie die pytz-Methode "Lokalisieren" verwenden, erfolgt die Zeitzonenumwandlung wie beabsichtigt um +09: 00, sodass Sie sich über diese Abweichung keine Gedanken machen müssen. ** ** **
tz.localize(d1)
>>> datetime.datetime(2020, 4, 19, 10, 20, 3, 201190, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
pytz 'localize ()' akzeptiert keine zeitzonenabhängigen Zeitzonen. Dieser Punkt braucht Aufmerksamkeit.
# localize offset ative
tz.localize(d1)
>>> datetime.datetime(2020, 4, 19, 10, 7, 47, 885883, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
# localize timezone aware (error)
tz.localize(d2)
# >>> ValueError: Not naive datetime (tzinfo is already set)
Wenn Sie sich also mit ** zeitzonenbewusster Zeit befassen, kann localize
nicht so verwendet werden, wie es ist, und es ist erforderlich, es einmal in nativen Offset zu konvertieren. ** Dies tritt häufig auf, wenn die zurückgegebene Zeit, z. B. die Verwendung eines Wrappers für eine externe API, zeitzonenabhängig ist.
Der hier geschriebene Inhalt erwähnt Pytz-Spezifikationen haben sich geändert | Qiita @ higitune, daher sollten Sie dort einen Blick darauf werfen. .. Es wird sehr hilfreich sein, einschließlich des Kommentarbereichs.
Wenn Sie ein Paket verwenden, das von einer anderen Person als Ihnen entwickelt wurde, ist es Sache des Implementierers, ob die vom Paketmodul zurückgegebene Zeit zeitzonenabhängig ist oder nativ versetzt ist. Um sie zu kombinieren und Ihre eigenen Entwicklungsanforderungen zu implementieren, müssen Sie eine Mischung aus diesen verwalten.
Daher ist es besser, es einmal auf dem Zeitstempel abzulegen (obwohl es sich in der Theory Street befindet). Mit dem folgenden Code können Sie JST sowohl Offset-native als auch zeitzonenabhängig konvertieren. (Es ist unbestätigt, ob ähnliche Ergebnisse in anderen Ländern erzielt werden können.)
import pytz
from datetime import datetime
DISPLAY_TIMEZONE = 'Asia/Tokyo'
tz = pytz.timezone(DISPLAY_TIMEZONE)
def localized_datetime(date: datetime):
return datetime.fromtimestamp(date.timestamp(), tz=tz)
if __name__ == '__main__':
# d1: native datetime
d1 = datetime.now()
print(f"d1: {d1}")
# d2: utc localize
d2 = tz.localize(d1)
print(f"d2: {d2}")
print(localized_datetime(d1))
print(localized_datetime(d2))
>>> d1: 2020-04-19 20:15:30.974272
>>> d2: 2020-04-19 20:15:30.974272+09:00
>>> 2020-04-19 20:15:30.974272+09:00
>>> 2020-04-19 20:15:30.974272+09:00
Die Zeitzone ist verwirrend ...
Der obige Code wird als Referenzimplementierung veröffentlicht, aber es scheint, dass die tatsächliche lokalisierte Zeit hauptsächlich für die Präsentationsschicht (dh das Erscheinungsbild) erforderlich ist, also in der Logikschicht und der Persistenzschicht so weit wie möglich mit datetime Ich denke, es wäre besser, stattdessen einen Zeitstempel zu verwenden.
Die Datums- und Uhrzeitangabe ist jedoch beim Schreiben von Code überwiegend bequemer, und ich denke, es gibt viele Fälle, in denen Datumsoperationen in der Logikschicht häufig ausgeführt werden müssen.
In einem solchen Fall halte ich es für besser, zu vereinheitlichen, welche der Zeitzonen awre / offset nativ verwendet wird, zumindest in dem Code, der näher an der von mir selbst geschriebenen Logikschicht liegt. Wenn die von externen Paketen verarbeiteten Zeiten inkonsistent sind, können Sie eine eigene Ebene erstellen, die die zu verwendende Schnittstelle dünn umschließt und die Inkonsistenz in Bezug auf Datums- und Uhrzeittyp und Zeitzone absorbiert. Ich denke, die Hauptlogik wird sauberer sein.
Ich kann mich nach meinem derzeitigen Kenntnisstand nicht entscheiden, an welche ich senden soll. Ich würde mich freuen, wenn Sie uns Ihre Meinung im Kommentarbereich mitteilen könnten.
Der obige Code enthält auch subtile Fallstricke. Zum Beispiel
"Der von der Funktion / Methode zurückgegebene Datum / Uhrzeit-Typ ist nativ versetzt, die Zeit basiert jedoch auf UTC."
In einem solchen Fall. Wenn die API des externen Dienstes so konzipiert ist, dass UTC konsistent zurückgegeben wird, und die externe Paketimplementierung, die sie umschließt, nicht cool ist und unter Berücksichtigung der Zeitzone keine Datums- / Uhrzeitangabe generiert ... Ich denke, es wird. .. .. In diesem Fall gehen wir individuell darauf ein.
Recommended Posts