segundos e data de salto

6

Acabei de descobrir que o tempo do Unix não inclui os segundos bissextos . Eu acho que é bastante surpreendente porque fazendo isso, está lentamente divergindo da UTC ... mas esse não é o ponto da minha pergunta.

Editar (3x): em resumo, veja abaixo e comentários para mais discussão:

Assumindo que o relógio do sistema segue o tempo Unix / POSIX ( não "real" UTC), como obter o número real de segundos decorridos desde a época do Unix (de date ou qualquer outro programa)?

Ou, pelo menos, há algum lugar em um arquivo "leap seconds" no Linux onde eu possa obter os segundos bissextos sem baixá-los manualmente?

Explicação sobre como cheguei à conclusão de que o relógio do meu sistema está configurado para o horário do Unix:

Lendo as seguintes linhas deste link sugerido por Richm :

As a result, for the most precise determination of epoch relative to the historic Gregorian calendar and UTC timescale, the user must subtract from the apparent NTP or POSIX epoch the relevant offset provided by the IERS.

Explicação sobre como cheguei à conclusão de que date --utc +%s realmente fornece o que chamamos de "timestamp do Unix":

O primeiro bissexto foi introduzido em 30 de junho de 1972.

Entre 01 Jan 1970 00:00:00 (época do Unix) e 01 de julho de 1972 00:00:00, podemos facilmente calcular que havia 365 + 365 + (31 + 29 + 31 + 30 + 31 + 30) dias + 1 segundo bissexto = 912 dias + 1 segundo bissexto = 78796801 segundos. Agora tente date -R --utc -d @78796801 ... Saída: Sáb, 01 jul 1972 00: 00: 0 1 !! Se você pensou (como eu fiz antes) que o timestamp Unix dá diretamente o número de segundos decorridos em nosso mundo real desde 01 Jan 1970 00:00:00 ... está errado!

Este exemplo prova que date considera o valor após o @ como um registro de data e hora real do Unix e fornece a data correspondente correta após a definição do horário do POSIX. Mas como usar o mesmo valor e dizem que este não é um timestamp mas um número de segundos reais desde a época? ...

[Não leia o seguinte: suposição inicial errada, guardo para "memória"]

date -R --utc && date -R --utc -d @$(date --utc +%s)

Interpretação da linha de comando:

O primeiro date dá a data definida no meu computador no UTC; o $(date ...) dá o tempo Unix, ou seja, o número de segundos desde a época do Unix menos o (25 este dia) pulo segundos; o date usando este parâmetro de tempo Unix como deveria dar uma data 25 segundos no passado em comparação com o primeiro comando se ele não gerenciasse adequadamente os segundos bissextos. Não é o caso, portanto, date deve estar "ciente dos segundos".

    
por Yanux 05.11.2014 / 16:13

1 resposta

1

Não encontrei uma solução simples para minha pergunta, então escrevi um pequeno script Bash para resolvê-lo. Você precisa baixar o arquivo leap seconds dado no link abaixo e colocá-lo com o script ou mudar o caminho para ele. Eu não escrevi utc2unix.sh ainda, mas é muito fácil de se adaptar. Não hesite em comentar / dar sugestões ...

unix2utc.sh :

#!/bin/bash

# Convert a Unix timestamp to the real number of seconds
# elapsed since the epoch.

# Note: this script only manage additional leap seconds

# Download leap-seconds.list from
# https://github.com/eggert/tz/blob/master/leap-seconds.list

# Get current timestamp if nothing is given as first param
if [ -z $1 ]; then
    posix_time=$(date --utc +%s)
else
    posix_time=$1
fi

# Get the time at which leap seconds were added
seconds_list=$(grep -v "^#" leap-seconds.list | cut -f 1 -d ' ')

# Find the last leap second (see the content of leap-seconds.list)
# 2208988800 seconds between 01-01-1900 and 01-01-1970:
leap_seconds=$(echo $seconds_list | \
               awk -v posix_time="$posix_time" \
               '{for (i=NF;i>0;i--)
                   if (($i-2208988800) < posix_time) {
                    print i-1; exit
                    }
                } END {if (($(i+1)-2208988800) == posix_time) 
                    print "Warning: POSIX time ambiguity:",
                            posix_time,
                          "matches 2 values in UTC time!",
                          "The smallest value is given." | "cat 1>&2"
                }')
# echo $leap_seconds

# Add the leap seconds to the timestamp
seconds_since_epoch=$(($posix_time + $leap_seconds))

echo $seconds_since_epoch

Apenas alguns testes:

  • date --utc +%s && ./unix2utc.sh - > hoje e pelo menos até junho de 2015, a diferença é de 25 segundos.
  • ./unix2utc.sh 78796799 - > %código%
  • 78796799 - > %código%
  • ./unix2utc.sh 78796801 - > 78796802 + no stderr: ./unix2utc.sh 78796800
por 06.11.2014 / 17:50