PEP 431 – Verbesserungen bei der Zeitzonenunterstützung
- Autor:
- Lennart Regebro <regebro at gmail.com>
- BDFL-Delegate:
- Barry Warsaw <barry at python.org>
- Status:
- Abgelöst
- Typ:
- Standards Track
- Erstellt:
- 11-Dez-2012
- Post-History:
- 11-Dez-2012, 28-Dez-2012, 28-Jan-2013
- Ersetzt-Durch:
- 615
Inhaltsverzeichnis
Zusammenfassung
Dieses PEP schlägt die Implementierung einer konkreten Zeitzonenunterstützung in der Python-Standardbibliothek vor und auch Verbesserungen an der Zeitzonen-API zur Behandlung mehrdeutiger Zeitan gaben während der Sommerzeitumstellung.
Rückzug
Nach langer Diskussion hat sich herausgestellt, dass die Dinge, die ich für Probleme in der Implementierung von datetime hielt, beabsichtigt sind. Dazu gehört das vollständige Ignorieren von Sommerzeitumstellungen bei der Datums-/Zeit-Arithmetik. Das macht die is_dst-Flags dieses PEPs bedeutungslos, da sie keine nützliche Funktion hätten. datetime trennt per Design nicht zwischen mehrdeutigen Datums- und Zeitangaben und wird dies auch nie tun.
Ich ziehe dieses PEP daher zurück.
UPDATE: Das PEP 615 „Unterstützung der IANA Time Zone Database in der Standardbibliothek“ fügte das Modul zoneinfo zu Python 3.9 hinzu und ersetzte dieses PEP.
Vorschlag
Konkrete Zeitzonenunterstützung
Die Zeitzonenunterstützung in Python hat außerhalb einer tzinfo-Basisklasse, die feste Offset-Werte unterstützt, keine konkrete Implementierung in der Standardbibliothek. Um Zeitzonen korrekt zu unterstützen, müssen Sie eine Datenbank über alle Zeitzonen, sowohl aktuelle als auch historische, einschließlich Sommerzeitumstellungen, einbeziehen. Aber solche Informationen ändern sich häufig, sodass selbst wenn wir die neuesten Informationen in einer Python-Version aufnehmen, diese Informationen nur wenige Monate später veraltet wären.
Daher war die Zeitzonenunterstützung nur über zwei Drittanbieter-Module verfügbar: pytz und dateutil, die beide die „zoneinfo“-Datenbank einbinden und wrappen. Diese Datenbank, auch „tz“ oder „The Olsen database“ genannt, ist die De-facto-Standard-Zeitzonendatenbank für Zeitzonen und ist in den meisten Unix- und Unix-ähnlichen Betriebssystemen enthalten, einschließlich OS X.
Dies gibt uns die Möglichkeit, den Code, der die Zoneinfo-Daten unterstützt, in die Standardbibliothek aufzunehmen, aber standardmäßig die Kopie der Daten des Betriebssystems zu verwenden, die normalerweise vom Aktualisierungsmechanismus des Betriebssystems oder der Distribution aktuell gehalten wird.
Für diejenigen, die ein Betriebssystem haben, das die Zoneinfo-Datenbank nicht enthält, z.B. Windows, wird die Python-Quellcode-Distribution eine Kopie der Zoneinfo-Datenbank enthalten, und eine Distribution, die die neueste Zoneinfo-Datenbank enthält, wird auch im Python Package Index verfügbar sein, sodass sie einfach mit Python-Paketverwaltungswerkzeugen wie easy_install oder pip installiert werden kann. Dies könnte auch auf Unix-Systemen geschehen, die keine Updates mehr erhalten und daher eine veraltete Datenbank haben.
Mit einem solchen Mechanismus hätte Python auf jeder Plattform eine vollständige Zeitzonenunterstützung in der Standardbibliothek, und eine einfache Paketinstallation würde eine aktualisierte Zeitzonendatenbank auf Plattformen bereitstellen, auf denen die Zoneinfo-Datenbank nicht enthalten ist, wie z.B. Windows, oder auf Plattformen, auf denen keine OS-Updates mehr bereitgestellt werden.
Die Zeitzonenunterstützung wird implementiert, indem das datetime-Modul in ein Paket umgewandelt wird und die Zeitzonenunterstützung zu datetime hinzugefügt wird, basierend auf Stuart Bishops pytz-Modul.
Ermitteln der lokalen Zeitzone
Auf Unix gibt es keine Standardmethode, um den Namen der verwendeten Zeitzone zu ermitteln. Alle verfügbaren Informationen sind die Zeitzonenabkürzungen wie EST und PDT, aber viele dieser Abkürzungen sind mehrdeutig, daher können Sie sich nicht darauf verlassen, um herauszufinden, in welcher Zeitzone Sie sich befinden.
Es gibt jedoch einen Standard, um die kompilierten Zeitzoneninformationen zu finden, da sie sich in /etc/localtime befinden. Daher ist es möglich, ein lokales Zeitzonenobjekt mit den korrekten Zeitzoneninformationen zu erstellen, auch wenn Sie den Namen der Zeitzone nicht kennen. Eine Funktion in datetime sollte bereitgestellt werden, um die lokale Zeitzone zurückzugeben.
Die Unterstützung dafür wird durch die Integration von Lennart Regebros tzlocal-Modul in das neue datetime-Modul erfolgen.
Für Windows wird der lokale Windows-Zeitzonenname nachgeschlagen und eine Abbildung zwischen Windows-Zeitzonennamen und Zoneinfo-Zeitzonennamen, die vom Unicode-Konsortium bereitgestellt wird, verwendet, um dies in eine Zoneinfo-Zeitzone umzuwandeln.
Die Abbildung sollte vor jeder Haupt- oder Bugfix-Version aktualisiert werden. Skripte dafür werden im Verzeichnis Tools/ bereitgestellt.
Mehrdeutige Zeiten
Beim Wechsel von der Sommerzeit (DST) wird die Uhr eine Stunde zurückgestellt. Das bedeutet, dass die Zeiten während dieser Stunde zweimal vorkommen, einmal mit DST und dann einmal ohne DST. Ebenso fehlt bei der Umstellung auf die Sommerzeit eine Stunde.
Die aktuelle Zeitzonen-API kann die beiden mehrdeutigen Zeiten während eines DST-Wechsels nicht unterscheiden. Zum Beispiel kommt in Stockholm die Zeit 2012-11-28 02:00:00 zweimal vor, sowohl bei UTC 2012-11-28 00:00:00 als auch bei 2012-11-28 01:00:00.
Die aktuelle Zeitzonen-API kann dies nicht auflösen, daher ist unklar, welche Zeit zurückgegeben werden soll.
# This could be either 00:00 or 01:00 UTC:
>>> dt = datetime(2012, 10, 28, 2, 0, tzinfo=zoneinfo('Europe/Stockholm'))
# But we can not specify which:
>>> dt.astimezone(zoneinfo('UTC'))
datetime.datetime(2012, 10, 28, 1, 0, tzinfo=<UTC>)
pytz löste dieses Problem, indem es is_dst-Parameter zu mehreren Methoden der tzinfo-Objekte hinzufügte, um es zu ermöglichen, Zeiten zu disambiguieren, wenn dies gewünscht ist.
Dieses PEP schlägt vor, diese is_dst-Parameter zu den relevanten Methoden der datetime-API hinzuzufügen und diese Funktionalität somit direkt in datetime zu integrieren. Dies ist wahrscheinlich der schwierigste Teil dieses PEP, da es die Aktualisierung der C-Version der datetime-Bibliothek mit dieser Funktionalität beinhaltet, da dies das Schreiben neuer Codes erforderte und nicht nur das Reorganisieren bestehender externer Bibliotheken.
Implementierungs-API
Die Zoneinfo-Datenbank
Die neueste Version der Zoneinfo-Datenbank sollte im Verzeichnis Lib/tzdata des Python-Quellcode-Verwaltungssystems vorhanden sein. Diese Kopie der Datenbank sollte vor jeder Python-Feature- und Bugfix-Version aktualisiert werden, aber nicht für Versionen von Python-Versionen, die sich im Nur-Sicherheitsfix-Modus befinden.
Skripte zur Aktualisierung der Datenbank werden in Tools/ bereitgestellt und die Release-Anweisungen werden aktualisiert, um diese Aktualisierung einzuschließen.
Neue Konfigurationsoptionen --enable-internal-timezone-database und --disable-internal-timezone-database werden implementiert, um die Installation dieser Datenbank beim Installieren aus dem Quellcode zu aktivieren und zu deaktivieren. Eine Quellcode-Installation wird standardmäßig diese installieren.
Binärinstallationsprogramme für Systeme, die eine systemseitig bereitgestellte Zoneinfo-Datenbank haben, können die mitgelieferte Datenbank von der Installation ausschließen, da sie für diese Plattformen nie verwendet würde. Für andere Plattformen, z.B. Windows, müssen Binärinstallationsprogramme die mitgelieferte Datenbank installieren.
Änderungen im datetime-Modul
Die öffentliche API der neuen Zeitzonenunterstützung enthält eine neue Klasse, eine neue Funktion, eine neue Ausnahme und vier neue Sammlungen. Zusätzlich erhalten mehrere Methoden des datetime-Objekts einen neuen is_dst-Parameter.
Neue Klasse dsttimezone
Diese Klasse bietet eine konkrete Implementierung der tzinfo-Basisklasse, die DST-Unterstützung implementiert.
Neue Funktion zoneinfo(name=None, db_path=None)
Diese Funktion nimmt einen Namensstring entgegen, der eine Zeichenkette sein muss, die eine gültige Zoneinfo-Zeitzone spezifiziert, d.h. „US/Eastern“, „Europe/Warsaw“ oder „Etc/GMT“. Wenn dieser nicht angegeben wird, wird die lokale Zeitzone nachgeschlagen. Wenn ein ungültiger Zeitzonenname angegeben wird oder die lokale Zeitzone nicht abgerufen werden kann, löst die Funktion UnknownTimeZoneError aus.
Die Funktion nimmt auch einen optionalen Pfad zum Speicherort der zu verwendenden Zoneinfo-Datenbank entgegen. Wenn nicht angegeben, sucht die Funktion in folgender Reihenfolge nach Datenbanken:
- Prüfen, ob das Modul
tzdata-updateinstalliert ist, und dann diese Datenbank verwenden. - Die Datenbank in
/usr/share/zoneinfoverwenden, falls vorhanden. - Die von Python bereitgestellte Datenbank in
Lib/tzdataverwenden.
Wenn keine Datenbank gefunden wird, wird eine UnknownTimeZoneError oder eine Unterklasse davon ausgelöst, mit einer Meldung, die erklärt, dass keine Zoneinfo-Datenbank gefunden werden kann, aber dass Sie eine mit dem Paket tzdata-update installieren können.
Neuer Parameter is_dst
Ein neuer is_dst-Parameter wird zu mehreren Methoden hinzugefügt, um Zeitmehrdeutigkeiten während der DST-Übergänge zu behandeln.
tzinfo.utcoffset(dt, is_dst=False)tzinfo.dst(dt, is_dst=False)tzinfo.tzname(dt, is_dst=False)datetime.astimezone(tz, is_dst=False)
Der is_dst-Parameter kann False (Standard), True oder None sein.
False gibt an, dass die angegebene Datum-Zeit als nicht während der Sommerzeit interpretiert werden soll, d.h. dass die angegebene Zeit nach der Umstellung von DST liegt. Dies ist der Standard, um das bestehende Verhalten beizubehalten.
True gibt an, dass die angegebene Datum-Zeit als während der Sommerzeit liegend interpretiert werden soll, d.h. dass die angegebene Zeit vor der Umstellung von DST liegt.
None löst eine Ausnahme AmbiguousTimeError aus, wenn die angegebene Zeit während einer DST-Umstellung lag. Es löst auch eine NonExistentTimeError aus, wenn eine Zeit während der „fehlenden Zeit“ bei einer Umstellung auf DST angegeben wird.
Neue Ausnahmen
UnknownTimeZoneErrorDiese Ausnahme ist eine Unterklasse von KeyError und wird ausgelöst, wenn eine Zeitzonenspezifikation angegeben wird, die nicht gefunden werden kann.
>>> datetime.zoneinfo('Europe/New_York') Traceback (most recent call last): ... UnknownTimeZoneError: There is no time zone called 'Europe/New_York'
InvalidTimeErrorDiese Ausnahme dient als Basis für
AmbiguousTimeErrorundNonExistentTimeError, um es zu ermöglichen, diese beiden separat abzufangen. Sie wird von ValueError erben, sodass Sie diese Fehler zusammen mit Eingaben wie dem 29. Februar 2011 abfangen können.AmbiguousTimeErrorDiese Ausnahme wird ausgelöst, wenn eine Datum-Zeit-Spezifikation angegeben wird, die mehrdeutig ist, während
is_dstauf None gesetzt ist.>>> datetime(2012, 11, 28, 2, 0, tzinfo=zoneinfo('Europe/Stockholm'), is_dst=None) >>> Traceback (most recent call last): ... AmbiguousTimeError: 2012-10-28 02:00:00 is ambiguous in time zone Europe/Stockholm
NonExistentTimeErrorDiese Ausnahme wird ausgelöst, wenn eine Datum-Zeit-Spezifikation für eine Zeit angegeben wird, die aufgrund von Sommerzeit nicht existiert, während
is_dstauf None gesetzt ist.>>> datetime(2012, 3, 25, 2, 0, tzinfo=zoneinfo('Europe/Stockholm'), is_dst=None) >>> Traceback (most recent call last): ... NonExistentTimeError: 2012-03-25 02:00:00 does not exist in time zone Europe/Stockholm
Neue Sammlungen
all_timezonesist die vollständige Liste der Zeitzonennamen, die verwendet werden können, alphabetisch sortiert.common_timezonesist eine Liste nützlicher, aktueller Zeitzonen, alphabetisch sortiert.
Das tzdata-update-Paket
Die Zoneinfo-Datenbank wird für einfache Installationen mit easy_install/pip/buildout als Paket bereitgestellt. Dieses Paket installiert keinen Python-Code und enthält keinen Python-Code außer dem, der für die Installation benötigt wird.
Es wird mit denselben Werkzeugen wie die interne Datenbank aktuell gehalten, aber immer dann veröffentlicht, wenn die zoneinfo-Datenbank aktualisiert wird, und verwendet dasselbe Versionsschema.
Unterschiede zur pytz API
pytzhat die Funktionenlocalize()undnormalize(), um zu umgehen, dasstzinfokein is_dst hat. Wennis_dstdirekt indatetime.tzinfoimplementiert ist, werden diese nicht mehr benötigt.- Die Funktion
timezone()wirdzoneinfo()genannt, um Kollisionen mit der in Python 3.2 eingeführten Klassetimezonezu vermeiden. zoneinfo()gibt die lokale Zeitzone zurück, wenn sie ohne Argumente aufgerufen wird.- Die Klasse
pytz.StaticTzInfodient dazu, dieis_dst-Unterstützung für statische Zeitzonen bereitzustellen. Wennis_dst-Unterstützung indatetime.tzinfoenthalten ist, wird sie nicht mehr benötigt. InvalidTimeErrorerbt vonValueError.
Ressourcen
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0431.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT