Почему разница с датой Unix составляет от 2 до 3 месяцев?

16

Как это возможно и как с этим бороться? Я делаю скрипт резервного копирования, который зависит от Unix dateи обнаружил интересную ошибку:

[root@web000c zfs_test]# date +%y-%m-%d --date='2 months ago'
14-04-01
[root@web000c zfs_test]# date +%y-%m-%d --date='3 months ago'
14-02-28
[root@web000c zfs_test]# date
Sun Jun  1 00:08:50 CEST 2014
уклоняющийся от работы человек
источник
Может ли это быть високосный год / ошибка 29 февраля? Вряд ли в таком инструменте, как date...
Марк Хендерсон

Ответы:

44

Вы наблюдаете это поведение из-за летнего времени (летнее время).

Поскольку в настоящее время вы находитесь в летнее время, когда ваши часы на час впереди, когда вы спрашиваете три месяца назад сразу после полуночи первого июня, время заканчивается на один час «раньше», потому что это не было летним временем три несколько месяцев назад.

Документация по дате GNU предлагает обойти это , используя 12:00 полудня и 15-е число месяца в качестве отправных точек при запросе относительных дней или месяцев соответственно. Например:

date +%y-%m-%d --date="$(date +%Y-%m-15) -3 month"
Майкл Хэмптон
источник
Спасибо. Да, ровно "3 месяца назад", наступившего в [root@web000c zfs_test]# date +%y-%m-%d --date='3 months ago' 14-03-01 [root@web000c zfs_test]# date Sun Jun 1 01:00:15 CEST 2014
01:00
Doh! Я думаю, что мне нужно пройти grep через некоторые из моих сценариев, так как я подозреваю, что пропустил это предложение по dateиспользованию.
Калеб
14

Если абсолютное время - ваша главная задача, вероятно, лучше работать вне UTC, поскольку оно существует для этой цели. Ответ Михаэля очень полезен, когда вам нужно поработать над проблемой, но обычно хорошей идеей является избегать ее полностью, где вы можете.

Если ваша система не установлена ​​в UTC по умолчанию, самый простой способ передать часовой пояс - это поставить перед командой префикс TZпеременной среды. Это ограничивает переключение зоны одной командой и предотвращает утечку переменной в ваши последующие команды.

$ NOW=$(date '+%s')
$ date -d @$NOW
Wed Jun 11 23:44:35 EDT 2014
$ TZ=UTC date -d @$NOW
Thu Jun 12 03:44:35 UTC 2014

Чего не следует делать, так это экспортировать TZпеременную, поскольку это может привести к путанице в устранении неполадок, как показано в следующем примере.

$ export TZ=UTC
$ date -d @$NOW
Thu Jun 12 03:44:35 UTC 2014
$ TZ=EDT date -d @$NOW
Thu Jun 12 03:44:35 EDT 2014
Андрей Б
источник
-3

В этот конкретный год, когда ваш компьютер считает, что его эксплуатируют, и в конкретную дату, которую вы выбрали для проверки «1 месяц назад, 2 месяца назад и 3 месяца назад, да - скорее всего, это обнаружение 29 февраля. Не всегда ошибка, но ..

Теперь сегодня НЕ 2014-06-01. Попробуйте еще раз. Установите дату компьютера на 2013-06-01. Попробуйте еще раз.
Установите дату компьютера на 2014-09-01. Попробуйте еще раз.

user225906
источник
6
Если вы предоставляете даты в американском MDYформате, используйте /E для разделения. Еще лучше, поскольку мы являемся международным сообществом здесь, используйте правильные даты ISO, такие как 2014-09-01.
glglgl