GNU Date:計算された日付間の日数が一致しません。

GNU Date:計算された日付間の日数が一致しません。

次のように2つの日付間の日数を計算しようとしています。

$ echo $((($(date +%s -d 2016/11/22)-$(date +%s -d 2016/11/20))/(3600*24))) days
2 days

これは予想される答えであり、次のものとまったく同じです。

$ date -d '2016/11/22 - 2 days'
Sun Nov 20 00:00:00 CET 2016

しかし、2つが一致しないようです。

$ echo $((($(date +%s -d 2020/06/28)-$(date +%s -d 2016/11/20))/(3600*24))) days
1315 days

$ date -d '2020/06/28 - 1315 days'
Mon Nov 21 00:00:00 CET 2016

私は何を逃したことがありませんか?使用する3番目のコマンドに1315日ではなく1316日が表示されないのはなぜですか?

もう少しテストをして、月を2020/06/28日付に変更しました。 3月には予想した回答を得たようです。11月20日4番目のコマンドでは、しかし4月から矛盾が発生します(つまり、11月21日4番目のコマンドで)。どのようなヒントがありますか?

ベストアンサー1

以下を考慮してください。

$ date +%s -d 2020/06/28
1593316800
$ date +%s -d 2016/11/20
1479618000
$ echo $(( 1593316800 - 1479618000 ))
113698800
$ echo $(( 113698800 / (3600*24) ))
1315                # integer, no rounding

$ echo $(( (3600*24) ))
86400
$ echo "113698800/86400" | bc
1315
$ echo "113698800/86400" | bc -l
1315.9583333333333333333
$ printf "%.0f\n" $(echo "113698800/86400" | bc -l)
1316                 # rounded to nearest integer

同様のksh2020計算問題:

$ printf "%(%s)T\n" 2020/06/28
1593365691
$ printf "%(%s)T\n" 2016/11/20
1479667133
$ echo $(( 1593365691 - 1479667133 ))
113698558
$ echo $(( 113698558/86400 ))
1315
$ echo "113698558/86400" | bc -l
1315.95553240740740740740

タイムゾーンをUTCに設定すると、問題が解決します。

$ cat test.sh
#!/bin/bash

edate="$1"
sdate="$2"

medate=$(date +%s -d $edate)
msdate=$(date +%s -d $sdate)
secs=$(( medate - msdate ))

echo $(( secs / 86400))
echo "$secs / 86400" | bc -l
$
$ ./test.sh 2020/06/28 2016/11/20
1315
1315.95833333333333333333
$ sudo timedatectl set-timezone UTC
$  ./test.sh 2020/06/28 2016/11/20
1316
1316.00000000000000000000

あるいは、より簡単にこのdate -uオプションを使用して正しい結果を生成することもできます。

-u、--utc、--universal協定世界時(UTC)を印刷または設定します。

これは夏時間の問題のように見え、タイムゾーンの設定によって異なる場合があります。

おすすめ記事