GNU Date :несоответствие расчета количества дней между датами

Нашел решение, которое, как я и подозревал, касалось разрешений. Каким-то образом бит setgid был установлен в /bin/bash.

Левая система проблемная, правая рабочая :Solution

Чтобы решить проблему, я запускаю следующую команду:

   sudo chmod g-s /bin/bash

1
04.08.2020, 18:44
2 ответа

Рассмотрим следующее:

$ 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 print or set Coordinated Universal Time (UTC)

Судя по всему, это проблема перехода на летнее время, возможно, связанная с настройками часового пояса.

4
18.03.2021, 23:14

Ваш ответ точен, fpmurphy . Спасибо большое.

Переход с CET на CEST произошел в последнее воскресенье марта 29 марта 2020 г. Отсюда и недостающие 3600 секунд с апреля.

Я получаю правильный ответ, просто добавляя опцию-u к дате:

$ 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

(Если вы попробуете использовать 3599 вместо 3600, вы вернетесь к 1315 дням ).

2
18.03.2021, 23:14

Теги

Похожие вопросы