Whenever – biblioteca de manejo de fecha y hora segura en tipos y ante DST para Python
(github.com/ariebovenberg)- Whenever es una biblioteca de fecha y hora para Python que evita mediante tipos la mezcla de valores naive/aware y los errores de cálculo con DST en
datetime, y puede usarse con implementación en Rust o en Python puro - La biblioteca estándar
datetimeno siempre refleja DST, y se muestra el ejemplodatetime(2023, 3, 25, 22, tzinfo=ZoneInfo("Europe/Paris")) + timedelta(hours=8), que devuelve 6:00 en lugar de 7:00 aunque por DST se omitió una hora - El sistema de tipos no puede distinguir naive y aware usando un solo
datetime, pero Whenever separa tipos por caso de uso comoInstant,ZonedDateTimeyPlainDateTimepara que el verificador de tipos pueda detectar errores - En la tabla comparativa, Arrow y Pendulum no cumplen al mismo tiempo con seguridad ante DST, aware/naive tipado y rendimiento, mientras que Whenever sí ofrece DST-safe, aware/naive tipado y fast
- Aún está antes de la versión 1.0, por lo que la API puede cambiar en lanzamientos minor; los cambios se explican en el changelog y el verificador de tipos o el IDE pueden ayudar con los ajustes
El problema que Whenever busca resolver
- Whenever es una biblioteca que ayuda a escribir código de fecha y hora correcto y verificable por tipos en Python
- Ofrece una implementación en Rust y también una versión en Python puro para quienes no quieran usar Rust
- Está diseñada con base en conceptos probados usados en bibliotecas modernas de fecha y hora de otros lenguajes
- Se presenta como mucho más rápida que otras bibliotecas de terceros y, por lo general, incluso más rápida que la biblioteca estándar
- El lanzamiento 1.0 sigue en espera para pulir mejor la API de largo plazo, especialmente mientras recibe comentarios sobre duration
Limitaciones de datetime de la biblioteca estándar
datetimede Python ha crecido durante más de 20 años y tiene aspectos que no coinciden con lo que hoy se espera de una biblioteca moderna de fecha y hora-
Problema de cálculos con DST
datetimeno siempre toma en cuenta el Daylight Saving Time (DST)- En el código de ejemplo, si se suman 8 horas a las 22:00 del 25 de marzo de 2023 en la zona horaria
Europe/Paris, debería dar 7:00 porque por DST se saltó una hora, pero devuelve 6:00 - No es un bug, sino una decisión de diseño para considerar DST solo en cálculos donde intervienen dos zonas horarias
-
Problema de distinción de tipos naive/aware
- Con un solo tipo
datetime, el sistema de tipos no puede distinguir entre naive datetime y aware datetime - Una firma como
def schedule_meeting(at: datetime) -> None: ...no permite saber si espera un valor naive o aware
- Con un solo tipo
Comparación con Arrow y Pendulum
- Según la tabla comparativa, Whenever cumple con DST-safe, aware/naive tipado y fast
datetimesolo cumple con fast, pero no con DST-safe ni con aware/naive tipado- Arrow intenta ofrecer una API más amigable que la biblioteca estándar, pero no resuelve los problemas centrales
- Mantiene los mismos footguns
- La decisión de reducir todo a un solo tipo
arrow.Arrowhace que al verificador de tipos le resulte más difícil detectar errores
- Pendulum en 2016 se presentó con mejor manejo de DST y mejor rendimiento, pero solo corrige algunas trampas relacionadas con DST
- El rendimiento se ha deteriorado mucho con el tiempo
- Lleva una larga etapa de mantenimiento estancado, con solo 2 lanzamientos en los últimos 4 años, y todavía quedan muchos issues graves y antiguos
Funciones principales
- Soporta DST-safe arithmetic
- Previene bugs comunes con una API segura por tipos
- Corrige problemas que Arrow y Pendulum no pudieron resolver
- Está basada en conceptos probados y familiares
- Ofrece alto rendimiento
- Tiene buenas pruebas y documentación
- Soporta aritmética de fechas
- Soporta precisión de nanosegundos
- Ofrece soporte para SQLAlchemy
- El soporte para Pydantic está en beta
- Ofrece implementación en Rust y una opción en Python puro
- El soporte para free-threading está en beta
- Soporta per-interpreter GIL
Flujo de uso de ejemplo
- Importa tipos explícitos como
Instant,ZonedDateTimeyPlainDateTimepara representar distintos casos de uso Instant.now()identifica un momento específico sin complejidad de zona horaria ni calendario- Convierte la zona horaria de forma explícita, por ejemplo con
now.to_tz("Europe/Paris") PlainDateTime("2023-10-28 22:00")no se mezcla accidentalmente con otros tipos- Si se llama
add(hours=6), aparece unaNaiveArithmeticWarningindicando que el ajuste de hora local ignora DST - Es necesario asumir explícitamente una zona horaria con
assume_tz("Europe/Amsterdam")
- Si se llama
- Si se ejecuta
add(hours=6)sobreZonedDateTime, el resultado refleja la transición de DST y devuelve2023-10-29 03:00:00+01:00[Europe/Amsterdam] - Soporta comparación, redondeo y truncado, parsing de formatos ISO8601·RFC3339·RFC2822 y formateo con patrones personalizados
- Si hace falta, puede convertirse a
datetimede la biblioteca estándar o a la inversa - El uso detallado puede consultarse en feature overview y API reference
Restricciones y política de estabilidad
- El rango soportado es el calendario gregoriano proléptico desde el año 1 hasta 9999
- Los offsets de zona horaria están limitados a enteros en segundos, en consistencia con la IANA TZ DB
- Whenever sigue semantic versioning
- Antes de la 1.0, la API puede cambiar en lanzamientos minor
- Los breaking changes se explican en detalle en el changelog
- La API está completamente tipada, así que el verificador de tipos o el IDE pueden ayudar a adaptarse a cambios de API
Licencia e influencias de diseño
- Whenever se distribuye bajo MIT License
- El binary wheel incluye dependencias de Rust con licencias igualmente permisivas, como MIT y Apache-2.0
- Noda Time y Joda Time fueron pioneras en el enfoque de tipos por concepto, y la jerarquía de tipos de Noda Time inspira directamente el diseño de Whenever
- Temporal inspiró el manejo de casos complejos alrededor de la ambigüedad por DST y el redondeo
- El módulo
datetimede Python se usa ampliamente para el manejo de fecha y hora de bajo nivel en la implementación en Python puro de Whenever - También toma algunas ideas de Jiff
- La gráfica comparativa de benchmarks está adaptada del proyecto Ruff
Aún no hay comentarios.