Diferença horária entre duas datas ISO8601 com segunda parte fracionária

Diferença horária entre duas datas ISO8601 com segunda parte fracionária

Recebo os seguintes carimbos de data/hora do Alpine Linux:

2017-04-25T07:19:53.946109551Z    
2017-04-25T07:19:53.946155414Z

Como posso decodificá-los e saber quanto tempo se passou entre eles?

A pergunta vinculada fala sobre a época, enquanto aqui claramente não é.

Responder1

Em sistemas GNU:

d1=2017-04-25T07:19:53.946109551Z
d2=2017-04-25T07:19:53.946155414Z
printf '%s - %s\n' "$(date -d "$d2" +%s.%N)" "$(date -d "$d1" +%s.%N)" | bc

Daria a você a diferença de horário como um número de segundos em ponto flutuante.

Advertência: o número será fornecido usando ponto ( .) como separador decimal, mesmo em localidades onde é a vírgula ( ,).

Você poderia canalizar essa saída para tr . "$(locale decimal_point)"corrigi-la.

Ou, com zsh, você poderia fazer:

printf '%.9f\n' $(($(date -d "$d2" +%s.%N) - $(date -d "$d1" +%s.%N)))

em vez disso, você receberá um número com o separador decimal correto em sua localidade.

No entanto, desde então zshusa o doubleformato numérico do seu processador, você pode descobrir que ele fornece um número diferente à medida que números 1493104793.946109551atingem o limite de precisão desses números. bcnão tem esse problema, pois usa precisão arbitrária.

zshpossui recursos integrados de análise de tempo, portanto, também é possível escrever uma solução que funcione em sistemas não-GNU, como:

parse_iso8601_full() {
  local t
  typeset -Fg REPLY
  zmodload zsh/datetime
  TZ=UTC0 strftime -r -s t %Y-%m-%dT%H:%M:%S ${1%.*} &&
    REPLY=$t.${${1%Z}##*.}
}

parse_iso8601_full $d1; t1=$REPLY
parse_iso8601_full $d2; t2=$REPLY
printf '%.9f\n' $((t2 - t1))

informação relacionada