16 pontos por GN⁺ 2024-08-25 | 5 comentários | Compartilhar no WhatsApp
  • Entre as mudanças recentes do ECMAScript, a mais notável é a proposta Temporal
    • Essa API já pode ser usada por meio do polyfill fornecido pela equipe do FullCalendar
    • Uma das principais vantagens dessa API é que finalmente passamos a ter um objeto nativo para representar "Zoned Date Time"

O que é Zoned Date Time?

  • Ao lidar com datas humanas, normalmente omitimos o fuso horário e falamos apenas da data e da hora
  • Porém, o objeto Date do JavaScript lida apenas com números, então o significado original da data se perde
  • Por exemplo, ao registrar o momento de um pagamento com cartão, muita gente pode usar um código como este
    const paymentDate = new Date('2024-07-20T10:30:00');  
    
  • Nesse caso, o navegador calcula os milissegundos com base no fuso horário do usuário (CET). Mas a informação armazenada pode ser interpretada de forma diferente dependendo do fuso
  • Além do fato muito importante de que, em JavaScript, datas não usam UTC e sim POSIX, onde segundos bissextos são completamente ignorados, há também o problema de que, quando só restam números, o significado original da data desaparece
  • Muita gente acha que trabalhar em UTC ou transmitir datas em formato ISO é suficiente, mas isso não está correto, porque ainda pode haver perda de informação

UTC não é suficiente

  • Mesmo trabalhando com o formato ISO, ainda falta a informação de fuso horário na hora de exibir a data
  • A função que converte um timestamp em uma data legível por humanos não é injective (injetiva)
  • Por exemplo, se você viajar de Madri para Sydney e depois voltar, pode acabar confuso com questões de fuso horário no extrato bancário

Introdução à API Temporal

  • A API Temporal introduz o objeto Temporal.ZonedDateTime, que representa data e hora junto com o fuso horário
  • Ela propõe uma extensão do RFC 3339, apresentando um padrão para serializar e desserializar datas em formato de string
  • 1996-12-19T16:39:57-08:00[America/Los_Angeles]
    • Essa string representa 19 de dezembro de 1996 às 16:39:57
    • O offset é de -08:00 em relação ao UTC (o Horário Padrão do Pacífico, PST, ao qual Los Angeles pertence)
    • E ainda especifica o fuso horário correspondente ("Horário Padrão do Pacífico") para que aplicações com reconhecimento de fuso horário possam levá-lo em conta
  • Suporta vários sistemas de calendário (por exemplo: budista, chinês, Dangi, gregoriano, islâmico, persa, japonês etc.)

Operações básicas

Criação de datas
  • A API Temporal fornece ferramentas poderosas para lidar com fusos horários
  • Por exemplo, ao criar um objeto Temporal.ZonedDateTime, ela garante que o fuso horário seja refletido corretamente:
    const zonedDateTime = Temporal.ZonedDateTime.from({  year: 2024,  month: 8,  day: 16,  hour: 12,  minute: 30,  second: 0,  timeZone: 'Europe/Madrid'});  
    
  • Isso permite manter a hora correta mesmo com mudanças de fuso horário ou ajustes locais de horário, como DST
Comparação de datas
  • Objetos ZonedDateTime oferecem o método compare, que permite comparar dois ZonedDateTime:
    const one = Temporal.ZonedDateTime.from('2020-11-01T01:45-07:00[America/Los_Angeles]');  
    const two = Temporal.ZonedDateTime.from('2020-11-01T01:15-08:00[America/Los_Angeles]');  
    Temporal.ZonedDateTime.compare(one, two);  // => -1  
    
Recursos embutidos úteis
  • A propriedade hoursInDay retorna o número real de horas daquele dia:
    Temporal.ZonedDateTime.from('2020-03-08T12:00-07:00[America/Los_Angeles]').hoursInDay;  // => 23  (dia de início do DST)  
    
Conversão de fuso horário
  • Você pode alterar o fuso horário de um ZonedDateTime usando o método withTimeZone:
    zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+09:00[Asia/Tokyo]');  
    zdt.withTimeZone('Africa/Accra').toString(); // => '1995-12-06T18:24:30+00:00[Africa/Accra]'  
    
Operações aritméticas básicas
  • Você pode usar o método .add para somar ou subtrair datas de acordo com as regras de DST:
    zdt = Temporal.ZonedDateTime.from('2020-03-08T00:00-08:00[America/Los_Angeles]');  
    laterDay = zdt.add({ days: 1 });  // => 2020-03-09T00:00:00-07:00[America/Los_Angeles]  
    
Cálculo da diferença entre datas
  • O método .until calcula a diferença entre dois horários e a retorna como um objeto Temporal.Duration
    • Por exemplo, ele pode ser usado como zdt.until(other)

Conclusão

  • A API Temporal transforma de forma profunda a maneira como o JavaScript lida com tempo
  • Este artigo abordou a diferença entre datas legíveis por humanos e datas em UTC, além de como representá-las com precisão usando o objeto Temporal.ZonedDateTime
  • No próximo artigo, serão explorados outros objetos interessantes, como Instant, PlainDate e Duration

Opinião do GN⁺

  • O problema de lidar com datas e horários, que há muito tempo dificulta a vida de desenvolvedores JavaScript, deve ser resolvido com a API Temporal
  • Como ela consegue tratar automaticamente questões de fuso horário e DST, é muito útil no desenvolvimento de aplicações globais
  • Compatibilidade com o objeto Date existente e questões de migração ainda são pontos a considerar
  • A API Temporal foi projetada de forma clara e intuitiva e também se destaca no suporte à internacionalização, inclusive com suporte a vários sistemas de calendário
  • Espera-se que essa mudança aumente bastante a produtividade de desenvolvedores JavaScript

5 comentários

 
kyc1682 2024-08-26

Finalmente!

 
hongminhee 2024-08-26

Só para constar, o Deno já incorpora a API Temporal.

 
huiya 2024-08-26

Nossa, ao projetar serviços globais gigantes eu sempre sofria com datas
Quero muito testar isso uma vez

 
jjpark78 2024-08-26

Sério, finalmente não vai mais precisar usar moment ou dayjs?

 
GN⁺ 2024-08-25
Opiniões no Hacker News
  • Lidar com data e hora em Javascript é muito difícil

    • A biblioteca Moment confunde data e hora, causando muitos problemas
    • A biblioteca Arrow do Python comete o mesmo erro
    • A biblioteca Chrono do Rust é previsível e tem menos defeitos
    • Date do JS e Moment são difíceis de usar
  • Há expectativa de que a nova API resolva os problemas de fuso horário no JS

    • Ela consegue fazer parse de certos fusos horários com sucesso, mas em outros casos assume UTC
    • Sofri bastante com esse problema no emprego anterior
  • Uma função que converte um timestamp em uma data legível por humanos não é injetiva

    • Há confusão entre os conceitos de injetividade e boa definição
    • Para um timestamp t, não existe uma única data legível por humanos x
  • Piada sobre a curva de dificuldade no tratamento de tempo

    • Iniciantes usam apenas timestamps UTC
    • Intermediários insistem que é preciso armazenar e converter fusos horários
    • Especialistas voltam a usar apenas timestamps UTC
  • Se o artigo usasse mais exemplos de datas futuras, seria mais convincente

    • Ao registrar um timestamp, só são necessários UTC e localização
    • O exemplo do banco é apenas um problema de UX, não de perda de informação
  • Usuário se sente inseguro por não entender o tratamento de tempo

    • Pede recomendação de uma boa introdução para entender problemas de tratamento de tempo em linguagens como Python
  • Ter um bom padrão de datetime já é metade da batalha

    • A outra metade é alcançar ampla adoção
    • Para compatibilidade com outros sistemas, é mais seguro converter para strings ISO ou timestamps Unix
  • Strings de data ISO devem capturar a informação correta

    • Há dúvida sobre a ideia de que JavaScript ou outras linguagens precisem de uma estrutura embutida
    • Temporal e Date resolvem problemas simples de forma complicada
  • Pergunta sobre como lidar com esse problema no Postgres

  • Faltam evidências de que Temporal realmente será adotado

    • Como várias propostas promissoras de JS, isso vem sendo discutido há muito tempo