2 pontos por GN⁺ 2024-12-27 | 1 comentários | Compartilhar no WhatsApp
  • O tempo POSIX/Unix costuma ser descrito como o número de segundos desde 1970-01-01 00:00:00, mas na prática é um valor baseado em UTC que ignora segundos intercalares, então não corresponde exatamente aos segundos reais transcorridos
  • Em 2024-12-25 18:51:26 UTC, o tempo POSIX é 1735152686, enquanto o total real de segundos transcorridos desde a epoch é 1735152713, uma diferença de 27 segundos
  • A IEEE 1003.1, ao definir seconds since the Epoch, sempre calcula um dia como 86.400 segundos, e o apêndice da norma também ignora os 14 segundos intercalares adicionados desde 1970 por questões de compatibilidade e facilidade de cálculo
  • O UTC adiciona segundos intercalares para reduzir a diferença em relação ao dia solar, e nesse momento o tempo POSIX pode dar um salto para trás, o que já causou incidentes em sistemas como Linux, Qantas e Cloudflare DNS
  • Para medir intervalos de tempo em um único computador, é melhor usar CLOCK_MONOTONIC ou CLOCK_BOOTTIME; se for necessário alinhar com timestamps POSIX, vale considerar leap smear ou conversão POSIX↔TAI

O tempo POSIX não é a contagem real de segundos transcorridos

  • JavaScript Date, GNU coreutils, Linux time(2), Go time.Unix, MySQL datetime, Ruby Time, Cassandra timestamp e outros costumam tratar o tempo POSIX como se fosse o número de segundos desde a Unix epoch
  • Mas essa descrição não bate exatamente com a intuição comum nem com a precisão técnica
    • Exemplo de horário: 2024-12-25 18:51:26 UTC
    • Tempo POSIX: 1735152686
    • Segundos reais transcorridos desde a epoch POSIX: 1735152713
    • Diferença: 27 segundos
  • Essa diferença existe porque o tempo POSIX deriva do UTC na IEEE 1003.1, mas assume que todos os dias têm exatamente 86.400 segundos
  • A definição da norma para seconds since the Epoch calcula o valor usando tm_sec, tm_min, tm_hour, tm_yday e tm_year, e não define a relação com anos anteriores a 1970 nem com valores negativos
  • Na prática, um dia nem sempre tem 86.400 segundos e esse valor varia ao longo do tempo
    • Astrônomos declaram periodicamente segundos intercalares para evitar que a data UTC se afaste demais do dia solar
    • Como resultado, o tempo POSIX pode dar um salto para trás a cada alguns anos
    • E um dia também pode dar um salto para a frente
  • Segundos intercalares já causaram falhas reais

O compromisso da norma e alternativas práticas

  • O apêndice B da IEEE 1003 resume que, no momento da publicação da norma, 14 segundos intercalares haviam sido adicionados desde 1970-01-01, mas esses 14 segundos foram ignorados para facilitar cálculos e manter compatibilidade
  • A norma assume que, na maioria dos sistemas, o valor de “time” continua aumentando e escolhe exigir que ele aumente mesmo durante um segundo intercalar
    • Ao mesmo tempo, parte do princípio de que a maioria dos sistemas não rastreia segundos intercalares ou pode não estar sincronizada com um padrão oficial de tempo
    • Por isso, não exige que seconds since the Epoch represente necessariamente a contagem exata de segundos entre o instante de referência e a epoch
    • Basta que aplicações possam tratar esse valor como segundos desde a epoch, e a precisão necessária fica a cargo do fornecedor e do administrador do sistema
  • Em aplicações distribuídas, eventos são sincronizados por timestamps, então uma interpretação consistente pode ser importante
    • O acúmulo de segundos intercalares não é previsível
    • O número de segundos intercalares desde a epoch pode continuar aumentando
    • A norma está mais preocupada com sincronização temporal entre aplicações em períodos astronomicamente curtos
  • Sistemas reais normalmente continuam funcionando mesmo com pequenas discrepâncias de tempo, mas como segundos intercalares são raros e a intuição linear de “segundos desde a epoch” é muito forte, bugs não percebidos podem se acumular
  • As alternativas dependem do cenário
    • Se você só precisa calcular a duração entre dois eventos no mesmo computador, use CLOCK_MONOTONIC ou, melhor ainda, CLOCK_BOOTTIME
    • Se não houver necessidade de trocar timestamps com outros sistemas que assumem tempo POSIX, use TAI, GPS, LORAN
    • Se precisar manter compatibilidade aproximada com sistemas de timestamp POSIX, use leap smear para distribuir o segundo intercalar ao longo de um intervalo maior
    • Bibliotecas como t-a-i, de qntm permitem converter entre POSIX e TAI
  • esforços para abolir os segundos intercalares, com expectativa de implementação até 2035
    • Isso exigirá trabalho extra para adicionar tabelas de conversão em tudo que depende da premissa de um dia = 86.400 segundos
    • Para horários após 2035, perguntas como “quantos segundos existem entre dois instantes?” podem se tornar muito mais simples

1 comentários

 
GN⁺ 2024-12-27
Comentários do Hacker News
  • Acabei de ler o romance de ficção científica de 2000 de Vernor Vinge, A Deepness in the Sky, e é um livro excelente que traz uma menção inesperada a segundos desde a epoch (seconds since the epoch)
    Começa com “Veja o modo como os Traders medem o tempo…” e descreve que os Qeng Ho contam em segundos a partir do momento em que a humanidade pisou pela primeira vez na Lua da Velha Terra, mas, olhando mais de perto, o ponto inicial na verdade era cerca de 15 milhões de segundos depois disso: o segundo zero de um dos primeiros sistemas operacionais de computador da humanidade

    • Esse livro é pessoalmente um dos meus favoritos de todos os tempos, e gosto muito da forma como ele usa referências sutis a software
      Se você quiser mais “ciência da computação no espaço”, recomendo a série Bobiverse; se quiser mais exploração de “humanos + simulação + computadores”, recomendo Permutation City
  • Sempre que leio sobre medição do tempo, inevitavelmente aprendo algo novo. Eu achava que o tempo Unix era a forma mais simples de acompanhar o tempo, desde que se considerasse apenas o rollover, e eu sabia dos segundos intercalares, mas nunca tinha pensado que eles também se aplicavam aqui
    Também li o link “UTC, GPS, LORAN and TAI”, e é um contraste interessante o fato de que o tempo GPS não leva segundos intercalares em conta

    • Dizer que algo aconteceu alguns segundos antes/depois é simples. O difícil é atribuir esse instante a uma data de calendário
    • No fim, passei a ver TAI como a opção mais simples, e os outros formatos deveriam ser usados convertendo a partir do TAI apenas quando necessário, por exemplo para exibição ou interoperabilidade
  • Não gosto muito do plano de “eliminar segundos intercalares até 2035”
    O ponto central do UTC é estar afastado do TAI por um número inteiro de segundos e permanecer próximo do tempo solar médio (MST). Se ele não vai mais acompanhar o MST, então deveríamos simplesmente migrar para TAI
    Se deixarem o UTC se afastar do MST, os segundos intercalares do passado ainda terão de ser tratados, mas ficarão em um meio-termo em que esses segundos intercalares já não têm mais propósito

    • Concordo que afastar-se do MST custa mais do que traz benefícios
      Ainda assim, essa proposta não é totalmente sem sentido. O objetivo é não mudar a gestão do tempo UTC existente, e fazer com que a diferença entre dois timestamps posteriores a 2035 seja o número exato de segundos físicos
      Mesmo assim, como o MST já é uma função do UTC, removê-la parece ridículo
    • Em um mundo ideal, sistemas de computador teriam usado TAI para acompanhar o tempo e convertido para UTC ou horário local usando o banco de dados TZ
      Mas, na prática, muitos sistemas fizeram a escolha errada, e o UNIX é o principal culpado. Essa escolha está profundamente enraizada em inúmeros sistemas e regulamentações, então “simplesmente migrar para TAI” é praticamente impossível
      Por isso é mais fácil reinterpretar o UTC como o “novo TAI”. Eu não ficaria surpreso se algum dia o antigo UTC reaparecesse com outro nome
    • Não existe uma entidade separada chamada TAI. O TAI é o que se obtém partindo do UTC e subtraindo a quantidade de segundos intercalares de interesse. O TAI não é mantido como uma grandeza padronizada separada
      Na maioria dos países, ou em todos eles, o horário civil se baseia no UTC. Ninguém vai atrasar todos os relógios do mundo em uns 30 segundos só porque isso é um pouco mais puro
      O tempo GPS também tem um offset em relação ao TAI, mas ninguém se importa muito. O Unix epoch é a mesma coisa; basta que o resultado seja consistente
    • O hack é literalmente trivial. Uma vez por mês, verifique se UTC # ET; se for diferente, crie um arquivo chamado Leap_Second. Todo mês, veja se esse arquivo existe; se existir, apague-o, some 1 ao valor do arquivo Leap_Seconds e crie um backup chamado LSSE
      “You are not expected to understand this.” É uma forma de manter os dois sistemas. Se quiser, também dá para fazer com hash ou tabela de consulta
  • Também é importante notar que a epoch UTC moderna é 1º de janeiro de 1972. Antes disso, o UTC usava um comprimento de segundo diferente do TAI
    No fim de 1971, como etapa intermediária, houve exatamente o último salto irregular de 0,107758 segundo TAI, e a soma dos pequenos degraus de tempo e ajustes de frequência do UTC ou TAI entre 1958 e 1971 foi ajustada para dar exatamente 10 segundos. Assim, 1972-01-01 00:00:00 UTC era exatamente 1972-01-01 00:00:10 TAI, e desde então a diferença passou a ser de segundos inteiros
    Ao mesmo tempo, a taxa de ticks do UTC passou a ser exatamente igual à do TAI, e o UTC começou a acompanhar UT1 em vez de UT2. Portanto, o tempo Unix de 1970 e 1971 não corresponde ao tempo UTC real daquele período
    https://en.wikipedia.org/wiki/Coordinated_Universal_Time#His...
    https://en.wikipedia.org/wiki/Unix_time#UTC_basis

    • Por causa disso, há pessoas vivas hoje que não conseguem saber, e nunca conseguirão saber, sua idade exata (em segundos)
      Isso vale mesmo supondo que o horário na certidão de nascimento seja preciso até o segundo. Durante parte da vida dessas pessoas, o valor considerado como “duração de 1 segundo” era bem diferente do que normalmente pensamos hoje como 1 segundo
      Aqui, segundo significa o segundo definido pela frequência de transição hiperfina do estado fundamental não perturbado do átomo de césio-133, de 9.192.631.770/s
  • Recentemente escrevi um código para uma corretora, e esse sistema rodava em VAX — ou, mais precisamente, em OpenVMS — e o epoch era 17 de novembro de 1858
    Foi a primeira vez na minha carreira que vi um epoch que não era Unix e, felizmente, no código que eu usava isso estava abstraído como epoch Unix

    • O epoch de 1858 parece vir do Julian Day, o calendário padrão da astronomia. Nele, o dia 0 é em 4713 a.C.
      https://www.slac.stanford.edu/~rkj/crazytime.txt
      Para fazer essas datas caberem na memória dos computadores dos anos 1950, deslocaram o calendário em 2,4 milhões de dias, e o resultado foi que o dia 0 virou 17 de novembro de 1858
    • Há também uma velha história da Microsoft sobre o conflito entre o epoch do Excel, 1º de janeiro de 1900, e o do Basic, 31 de dezembro de 1899
      https://www.joelonsoftware.com/2006/06/16/my-first-billg-rev...
    • Outro sistema computacional comum que vale conhecer: o epoch do Windows é 1º de janeiro de 1601
    • O MacOS clássico, o sistema de arquivos HFS da Apple (também usado no OS X) e o PalmOS tinham todos como epoch 1º de janeiro de 1904
      A API Foundation do macOS/Swift NSDate.timeIntervalSinceReferenceDate usa 1º de janeiro de 2001 como epoch
      A Wikipedia também tem uma lista útil: https://en.wikipedia.org/wiki/Epoch_(computing)#Notable_epoc...
    • O PostgreSQL usa internamente um epoch 2000-01-01 para armazenar timestamps
  • Alguns instantes não podem ser representados como timestamp POSIX, e alguns timestamps POSIX acabam não correspondendo a um tempo real

    • Fico curioso para saber quais são os timestamps POSIX que não correspondem a um tempo real. Ou isso se refere ao caso de haver um segundo bissexto negativo no futuro?
    • Isso sempre foi assim. No tempo Unix, datas anteriores a 1970 não são definidas
    • Ainda assim, pelo menos nenhum timestamp POSIX corresponde a mais de um instante real. É melhor do que uma única forma de representação que as pessoas usam para tudo
    • Não é bem assim
      Isso é parecido com dizer que existem instantes sem ano ISO 8601. Todos os instantes têm um ano, só que alguns anos são mais longos que outros
      Se você sentar e ficar olhando https://time.is/UTC, o tempo vai aumentar de forma monotônica, e de vez em quando algum segundo será só um pouquinho mais longo. Por exemplo, algo como 0,001% mais longo ao longo de 24 horas
  • Ao armazenar datas em um banco de dados, sempre as salvo como tempo Unix epoch e não registro informações de fuso horário no campo de data. Se houver requisito de saber o fuso, armazeno isso separadamente
    Fico me perguntando se, em vez disso, eu deveria armazenar timestamps no formato TAI e usar uma função para convertê-los para UTC quando necessário, de modo a lidar com correções relacionadas à Terra quando elas forem necessárias
    Sei que fusos horários são um campo minado, mas eles também são uma construção humana cujos limites mudam com o tempo. Parece que o certo seria fixar em tempo absoluto e, quando necessário, renderizar no formato de horário local desejado

    • Exato. TAI ou um formato semelhante é a única forma razoável de acompanhar o tempo “do sistema”, e sistemas de nível mais alto deveriam convertê-lo para o tempo visto por humanos
      Ajustes de segundos bissextos deveriam acontecer no mesmo lugar que conversões de fuso horário. Infelizmente, o Unix padronizou a coisa errada, e a migração é difícil
    • Em geral não, e quase nunca. A maior parte do software é escrita para suavizar/mascarar segundos bissextos, e na prática eles só aparecem na camada de sincronização de relógio. Por exemplo, o chrony implementa leap smearing
      Portanto, todos os relógios acabam alinhados ao UTC de qualquer forma. Converter de UTC para TAI ao armazenar e depois voltar ao ler viraria uma bagunça
    • Sobre a parte “não registro informações de fuso horário no campo de data”: na prática, pouquíssimos bancos de dados permitem preservar o fuso horário em uma coluna de timestamp
      Normalmente o banco de dados não tem conceito de fuso horário para o timestamp armazenado (SQL Server), ou oferece um tipo de timestamp “com consciência de fuso”, mas converte a entrada para UTC e descarta o fuso original (MySQL, Postgres)
      Até onde sei, só o Oracle consegue preservar de fato, em ida e volta, um fuso que não seja local no tipo with time zone
    • Depende do que o sistema armazena. A maioria dos sistemas não se importa de estar 1 segundo errado a cada alguns anos
      Em alguns cálculos, uma diferença de 1 segundo é um problema grande. É preciso ter cuidado ao adotar algo que não seja o formato mais amplamente usado, e deve haver um bom motivo para se afastar do padrão. Só o fato de ser diferente já pode gerar um custo alto
    • Basta usar os campos nativos de data e hora do banco de dados
  • Sinto que este texto estragou meu Natal. Nada é sagrado? Segundos deveriam ser segundos desde o epoch
    Não entendo por que deveríamos nos importar com um pequeno desvio em relação ao dia solar. O conversor que transforma segundos desde o epoch em uma representação de data não deveria ser responsável por aplicar as correções?

    • O jeito atual é, na verdade, o jeito que queremos. 86400 segundos = 1 dia, e operamos sob a suposição de que a meia-noite UTC é sempre um múltiplo de 86400
      Não quero que todo software tenha que hardcodar a introdução de segundos bissextos, lidar com smearing e exigir um método de atualização dentro de um mês sempre que um novo segundo bissexto for introduzido
      Até agora não tivemos que nos preocupar nem pensar nisso, e não precisaremos no futuro. Está sendo tratado do jeito certo
  • Segundos bissextos deveriam ser substituídos por foguetes gigantes instalados no equador. Em vez de ajustar os relógios, vamos ajustar o planeta

    • Se um erro de cálculo deixar a Terra lenta ou rápida demais, acho que não seria tão engraçado
      Na tradição islâmica, nas histórias sobre o fim dos tempos e o anticristo (Dajjal), há um trecho em que algo assim realmente acontece. Dizem que “o primeiro dia do anticristo será como um ano, o segundo dia como um mês e o terceiro dia como uma semana”, e muitos entendem isso literalmente: a rotação da Terra realmente desaceleraria e, no fim, inverteria de direção, fazendo o sol nascer no oeste. Esse seria o último sinal do fim da humanidade
  • Mesmo que, por causa dos segundos intercalares, o epoch tenha ficado 29 segundos mais distante no passado do que date +%s dá a entender, fico pensando: e daí?
    O fato de todos concordarem com algum número N que representa a hora atual é muito mais importante. Esses -29 segundos hipotéticos não afetam o mundo real. Não é como se alguém fosse executar uma rotina de mira de míssil contra um alvo de 30 anos atrás
    Sou a favor de abolir os segundos intercalares, mas não acho útil enfatizar a discrepância de tempo. Mesmo que, tecnicamente, isso esteja correto

    • Dá para imaginar uma situação em que a duração de um evento curto seja calculada pelos horários de início/fim. Se esse intervalo atravessar um segundo intercalar, dependendo de como os timestamps forem tratados, a duração pode variar bastante
      O mais importante é o impacto no futuro. O fato de timestamps do passado poderem diferir em alguns segundos de um simples cálculo “agora - N segundos” é, na maioria das vezes, mais uma curiosidade; mas a possibilidade de que, em algum momento no futuro, todos os relógios precisem ser deslocados mais 1 segundo é mais importante. Há muitos casos reais em que levar isso em conta exige um esforço considerável
    • Para algumas coisas, isso importa. Sem esses segundos intercalares hipotéticos, por exemplo, a posição do sol ao meio-dia local ficaria deslocada em 29 segundos