两个带有小数第二部分的 ISO8601 日期之间的时差

Yak*_*kov 0 timestamps alpine-linux

我从 Alpine Linux 收到以下时间戳:

2017-04-25T07:19:53.946109551Z    
2017-04-25T07:19:53.946155414Z
Run Code Online (Sandbox Code Playgroud)

我如何解码它们并知道它们之间经过了多少时间?

链接的问题讨论了纪元时间,而这里显然不是。

Sté*_*las 5

在 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
Run Code Online (Sandbox Code Playgroud)

会给你一个浮点秒数的时间差。

警告:.即使在使用逗号 ( ,) 代替的语言环境中,也将使用句点 ( ) 作为小数点分隔符来给出数字。

您可以将该输出通过管道tr . "$(locale decimal_point)"进行修复。

或者,使用zsh,您可以执行以下操作:

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

相反,它会给你一个在你的语言环境中带有正确小数点分隔符的数字。

但是,从那时起zsh使用double处理器的数字格式,您可能会发现它给出了不同的数字,因为数字1493104793.946109551达到了这些数字的精度限制。bc没有问题,因为它使用任意精度。

zsh 内置了时间解析功能,因此您还可以编写一个适用于非 GNU 系统的解决方案,例如:

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))
Run Code Online (Sandbox Code Playgroud)