On GNU systems:
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
Would give you the time difference as a floating point number of seconds.
Caveat: the number will be given using period (.
) as the decimal separator even in locales where it's the comma (,
) instead.
You could pipe that output to tr . "$(locale decimal_point)"
to fix it.
Or, with zsh
, you could do:
printf '%.9f\n' $(($(date -d "$d2" +%s.%N) - $(date -d "$d1" +%s.%N)))
instead which will give you a number with the correct decimal separator in your locale.
However since then zsh
uses the double
number format of your processor, you may find that it gives a different number as numbers like 1493104793.946109551
reach the limit of precision of those numbers. bc
doesn't have the issue as it uses arbitrary precision.
zsh
has time parsing capabilities builtin, so one can also write a solution that will work on non-GNU systems like:
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))