1 Punkte von GN⁺ 2025-04-14 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Whenever ist eine Datums- und Zeitbibliothek für Python, die die Vermischung von naive/aware datetime-Werten sowie Fehler bei DST-Berechnungen über Typen verhindert und entweder mit einer Rust-Implementierung oder als reine Python-Implementierung genutzt werden kann
  • Die Standardbibliothek datetime berücksichtigt DST nicht immer; als Beispiel wird gezeigt, dass datetime(2023, 3, 25, 22, tzinfo=ZoneInfo("Europe/Paris")) + timedelta(hours=8) trotz der durch DST übersprungenen Stunde 6 Uhr statt 7 Uhr zurückgibt
  • Das Typsystem kann mit einem einzigen datetime nicht zwischen naive und aware unterscheiden; Whenever trennt dagegen Typen nach Verwendungszweck wie Instant, ZonedDateTime und PlainDateTime, sodass Type-Checker Fehler erkennen können
  • Arrow und Pendulum erfüllen laut Vergleichstabelle nicht alle Anforderungen an DST-Sicherheit, typed aware/naive und Performance; Whenever wird als Unterstützung für alle Punkte DST-safe, typed aware/naive und fast dargestellt
  • Da es noch vor 1.0 ist, kann sich die API in Minor-Releases ändern; Änderungen werden im Changelog erläutert, und Type-Checker oder IDEs können bei der Anpassung helfen

Das Problem, das Whenever lösen will

  • Whenever ist eine Bibliothek, die dabei hilft, in Python korrekten und typprüfbaren Datums- und Zeitcode zu schreiben
  • Sie bietet eine Rust-Implementierung sowie eine reine Python-Version für Nutzer, die kein Rust verwenden möchten
  • Sie basiert auf bewährten Konzepten, die in Datums- und Zeitbibliotheken anderer moderner Sprachen verwendet werden
  • Sie wird als deutlich schneller als andere Third-Party-Bibliotheken und meist auch schneller als die Standardbibliothek beschrieben
  • Der 1.0-Release ist zurückgestellt, um die langfristige API weiter zu verfeinern; insbesondere wird Feedback zu duration eingeholt

Grenzen der Standardbibliothek datetime

  • Pythons datetime ist über mehr als 20 Jahre gewachsen und weist Stellen auf, die nicht zu den Erwartungen an moderne Datums- und Zeitbibliotheken passen
  • Problem bei DST-Berechnungen

    • datetime berücksichtigt Daylight Saving Time (DST) nicht immer
    • Im Beispielcode ergibt das Addieren von 8 Stunden zu 22 Uhr am 25. März 2023 in der Zeitzone Europe/Paris 6 Uhr, obwohl es wegen der durch DST übersprungenen Stunde 7 Uhr sein müsste
    • Das ist kein Bug, sondern eine Designentscheidung, nach der DST nur bei Berechnungen berücksichtigt wird, an denen zwei Zeitzonen beteiligt sind
  • Problem bei der Typunterscheidung zwischen naive/aware

    • Mit nur einem datetime-Typ kann das Typsystem nicht zwischen naive datetime und aware datetime unterscheiden
    • Eine Funktionssignatur wie def schedule_meeting(at: datetime) -> None: ... lässt nicht erkennen, ob naive oder aware erwartet wird

Vergleich mit Arrow und Pendulum

  • Nach den Kriterien der Vergleichstabelle erfüllt Whenever DST-safe, typed aware/naive und fast vollständig
  • datetime erfüllt nur den Punkt fast, nicht aber DST-safe und typed aware/naive
  • Arrow versucht, eine freundlichere API als die Standardbibliothek anzubieten, löst aber die Kernprobleme nicht
    • Es behält denselben Footgun bei
    • Die Entscheidung, die Typen auf einen einzigen Typ arrow.Arrow zu reduzieren, erschwert es Type-Checkern, Fehler zu erkennen
  • Pendulum trat 2016 mit besserem DST-Handling und Performance-Verbesserungen an, behebt aber nur einige DST-bezogene Fallstricke
    • Die Performance hat im Laufe der Zeit deutlich nachgelassen
    • Es befindet sich in einem langen Wartungsstillstand mit nur zwei Releases in den letzten vier Jahren, und viele schwerwiegende, alte Issues sind noch offen

Wichtige Funktionen

  • Unterstützt DST-safe arithmetic
  • Verhindert häufige Bugs durch eine typsichere API
  • Behebt Probleme, die Arrow und Pendulum nicht gelöst haben
  • Basiert auf bewährten und vertrauten Konzepten
  • Bietet hohe Performance
  • Verfügt über umfangreiche Tests und Dokumentation
  • Unterstützt Datumsarithmetik
  • Unterstützt Nanosekunden-Präzision
  • Bietet SQLAlchemy-Unterstützung
  • Pydantic-Unterstützung ist im Beta-Status
  • Bietet eine Rust-Implementierung und eine reine Python-Option
  • Free-Threading-Unterstützung ist im Beta-Status
  • Unterstützt per-interpreter GIL

Beispielhafter Nutzungsablauf

  • Explizite Typen wie Instant, ZonedDateTime und PlainDateTime werden importiert, um unterschiedliche Anwendungsfälle auszudrücken
  • Instant.now() identifiziert einen bestimmten Zeitpunkt ohne Komplexität durch Zeitzonen oder Kalender
  • Zeitzonen werden explizit umgewandelt, etwa mit now.to_tz("Europe/Paris")
  • PlainDateTime("2023-10-28 22:00") wird nicht versehentlich mit anderen Typen vermischt
    • Beim Aufruf von add(hours=6) entsteht eine NaiveArithmeticWarning, dass die lokale Zeitanpassung DST ignoriert
    • Die Zeitzone muss mit assume_tz("Europe/Amsterdam") explizit angenommen werden
  • Wird auf einem ZonedDateTime add(hours=6) ausgeführt, berücksichtigt das Ergebnis die DST-Umstellung und gibt 2023-10-29 03:00:00+01:00[Europe/Amsterdam] zurück
  • Unterstützt Vergleiche, Runden und Abschneiden, Parsing der Formate ISO8601, RFC3339 und RFC2822 sowie Formatierung mit benutzerdefinierten Patterns
  • Bei Bedarf kann in die Standardbibliothek datetime oder umgekehrt konvertiert werden
  • Ausführliche Nutzungshinweise finden sich in der feature overview und der API reference

Einschränkungen und Stabilitätspolitik

  • Der unterstützte Bereich ist der proleptische gregorianische Kalender von Jahr 1 bis 9999
  • Zeitzonen-Offsets sind konsistent mit der IANA TZ DB auf ganzzahlige Sekunden beschränkt
  • Whenever folgt semantic versioning
  • Vor 1.0 kann sich die API in Minor-Releases ändern
  • Breaking Changes werden ausführlich im Changelog erklärt
  • Da die API vollständig typisiert ist, können Type-Checker oder IDEs bei der Anpassung an API-Änderungen helfen

Lizenz und Einflüsse auf das Design

  • Whenever wird unter der MIT License veröffentlicht
  • Das Binary Wheel enthält Rust-Abhängigkeiten mit ähnlich permissiven Lizenzen wie MIT und Apache-2.0
  • Noda Time und Joda Time haben den Ansatz mit konzeptbezogenen Typen geprägt; die Typhierarchie von Noda Time inspirierte das Design von Whenever direkt
  • Temporal inspirierte die Behandlung komplexer Fälle rund um DST-Mehrdeutigkeiten und Rundung
  • Pythons datetime-Modul wird in der reinen Python-Implementierung von Whenever umfassend für Low-Level-Datums- und Zeitverarbeitung verwendet
  • Einige Ideen von Jiff wurden ebenfalls übernommen
  • Die Benchmark-Vergleichsgrafik wurde aus dem Projekt Ruff adaptiert

Noch keine Kommentare.

Noch keine Kommentare.