GNU Date: 계산된 날짜 사이의 일수가 일치하지 않습니다.

GNU Date: 계산된 날짜 사이의 일수가 일치하지 않습니다.

다음과 같이 두 날짜 사이의 일수를 계산하려고 합니다.

$ 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

그러나 두 가지가 일치하지 않는 것 같습니다.

$ 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

내가 뭐 놓친 거 없니? 사용하는 세 번째 명령에 1315일이 아닌 1316일이 표시되지 않는 이유는 무엇입니까?

좀 더 테스트를 해보고 월을 2020/06/28 날짜로 변경했습니다. 3월에는 예상했던 답변을 얻은 것 같습니다.11월 20일네 번째 명령에서) 그러나 4월부터 불일치가 나타납니다(즉,11월 21일네 번째 명령에서). 어떤 팁이 있나요?

답변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)를 인쇄하거나 설정합니다.

이는 일광 절약 시간제 문제인 것으로 보이며 시간대 설정에 따라 다를 수 있습니다.

답변2

당신의 대답은 정확합니다머피. 매우 감사합니다.

CET에서 CEST로의 변경은 2020년 3월 마지막 일요일인 2020년 3월 29일에 이루어집니다. 그러니까 4월에는 3600초가 빠졌네요.

정답을 얻기 위해 옵션을 추가했습니다.-유도착하다날짜:

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

분명히 누락된 시간(3600초)을 수동으로 추가하면 동일한 결과가 나타납니다.

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

(3600이 아닌 3599를 사용하려고 하면 1315일로 돌아갑니다.)

관련 정보