1 pontos por GN⁺ 2025-04-14 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Whenever é uma biblioteca de data e hora para Python que evita, por meio de tipos, a mistura entre datetime naive/aware e erros de cálculo com DST, podendo ser usada com implementação em Rust ou em Python puro
  • A biblioteca padrão datetime nem sempre reflete o DST, e é apresentado o exemplo em que datetime(2023, 3, 25, 22, tzinfo=ZoneInfo("Europe/Paris")) + timedelta(hours=8) retorna 6h, e não 7h, mesmo com uma hora tendo sido pulada por causa do DST
  • O sistema de tipos não consegue distinguir naive e aware usando apenas um datetime, mas o Whenever separa tipos por finalidade como Instant, ZonedDateTime e PlainDateTime, permitindo que o verificador de tipos capture erros
  • Na tabela de comparação, Arrow e Pendulum não conseguem atender simultaneamente a segurança contra DST, aware/naive tipado e desempenho, enquanto o Whenever afirma oferecer DST-safe, aware/naive tipado e fast
  • Ainda está antes da versão 1.0, então a API pode mudar em releases minor; as mudanças são explicadas no changelog, e verificadores de tipos ou IDEs podem ajudar na adaptação

O problema que o Whenever quer resolver

  • Whenever é uma biblioteca que ajuda a escrever código de data e hora correto e verificável por tipos em Python
  • Oferece uma implementação em Rust e também uma versão em Python puro para quem não quer usar Rust
  • Foi projetada com base em conceitos comprovados usados em bibliotecas modernas de data e hora de outras linguagens
  • É apresentada como muito mais rápida que outras bibliotecas de terceiros e, em geral, até mais rápida que a biblioteca padrão
  • O lançamento da versão 1.0 está adiado para refinar melhor a API de longo prazo, especialmente com feedback sobre duration

Limitações da biblioteca padrão datetime

  • O datetime do Python evoluiu por mais de 20 anos, mas tem aspectos que não condizem com o esperado de bibliotecas modernas de data e hora
  • Problema nos cálculos com DST

    • datetime nem sempre considera Daylight Saving Time (DST)
    • No código de exemplo, ao somar 8 horas a 22h de 25 de março de 2023 no fuso Europe/Paris, o resultado deveria ser 7h porque uma hora foi pulada pelo DST, mas retorna 6h
    • Isso não é um bug, mas uma decisão de design para considerar DST apenas em cálculos que envolvem dois fusos horários
  • Problema na distinção de tipos naive/aware

    • Apenas o tipo datetime não permite distinguir naive datetime e aware datetime no sistema de tipos
    • Uma assinatura como def schedule_meeting(at: datetime) -> None: ... não deixa claro se espera um valor naive ou aware

Comparação com Arrow e Pendulum

  • Pela tabela de comparação, o Whenever atende a DST-safe, aware/naive tipado e fast ao mesmo tempo
  • datetime atende apenas ao item fast, e não atende a DST-safe nem aware/naive tipado
  • Arrow tenta oferecer uma API mais amigável que a da biblioteca padrão, mas não resolve os problemas centrais
    • Mantém as mesmas armadilhas
    • A decisão de reduzir tudo a um único tipo arrow.Arrow torna mais difícil para o verificador de tipos capturar erros
  • Pendulum apresentou em 2016 melhor tratamento de DST e ganhos de desempenho, mas corrigiu apenas parte das armadilhas relacionadas a DST
    • O desempenho se deteriorou bastante com o tempo
    • Está em um longo período de estagnação de manutenção, com apenas dois releases nos últimos 4 anos, e ainda restam muitos issues graves e antigos

Principais recursos

  • Suporta DST-safe arithmetic
  • API com segurança de tipos para evitar bugs comuns
  • Corrige problemas que Arrow e Pendulum não conseguiram resolver
  • Baseia-se em conceitos comprovados e familiares
  • Oferece alto desempenho
  • Tem testes e documentação robustos
  • Suporta aritmética de datas
  • Suporta precisão de nanossegundos
  • Oferece suporte a SQLAlchemy
  • O suporte a Pydantic está em beta
  • Oferece implementação em Rust e opção em Python puro
  • O suporte a free-threading está em beta
  • Suporta per-interpreter GIL

Fluxo de uso de exemplo

  • Importa tipos explícitos como Instant, ZonedDateTime e PlainDateTime para representar casos de uso diferentes
  • Instant.now() identifica um instante específico sem complexidade de fuso horário ou calendário
  • Converte o fuso horário explicitamente com now.to_tz("Europe/Paris")
  • PlainDateTime("2023-10-28 22:00") não se mistura acidentalmente com outros tipos
    • Ao chamar add(hours=6), é emitido um NaiveArithmeticWarning informando que o ajuste de hora local ignora o DST
    • É preciso assumir explicitamente um fuso horário com assume_tz("Europe/Amsterdam")
  • Ao executar add(hours=6) em ZonedDateTime, o resultado reflete a transição de DST e retorna 2023-10-29 03:00:00+01:00[Europe/Amsterdam]
  • Suporta comparação, arredondamento e truncamento, parsing de formatos ISO8601·RFC3339·RFC2822 e formatação com padrão personalizado
  • Quando necessário, é possível converter para o datetime da biblioteca padrão ou fazer o caminho inverso
  • O uso detalhado pode ser consultado em feature overview e API reference

Restrições e política de estabilidade

  • O intervalo suportado vai do ano 1 ao 9999 no calendário gregoriano proléptico
  • O deslocamento de fuso horário é limitado a inteiros em segundos, em consistência com o IANA TZ DB
  • O Whenever segue semantic versioning
  • Antes da versão 1.0, a API pode mudar em releases minor
  • Mudanças incompatíveis são detalhadas no changelog
  • Como a API é totalmente tipada, verificadores de tipos e IDEs podem ajudar na adaptação a mudanças

Licença e influências de design

  • O Whenever é distribuído sob a MIT License
  • Os binary wheels incluem dependências Rust com licenças permissivas semelhantes, como MIT e Apache-2.0
  • Noda Time e Joda Time foram pioneiros na abordagem de tipos por conceito, e a hierarquia de tipos do Noda Time inspirou diretamente o design do Whenever
  • Temporal inspirou o tratamento de casos complexos em torno de ambiguidades de DST e arredondamento
  • O módulo datetime do Python é amplamente usado no processamento de baixo nível de data e hora na implementação em Python puro do Whenever
  • Algumas ideias de Jiff também foram incorporadas
  • O gráfico comparativo de benchmark foi adaptado do projeto Ruff

Ainda não há comentários.

Ainda não há comentários.