OSX не может преобразовать ISO8601 в эпоху

Я осваиваюсь на Mac OS, и некоторые из моих скриптов не работают после Linux. В частности, очень интересен один сценарий.

Итак, я пытаюсь преобразовать дату ISO8601 в эпоху Unix. Собственный способ OSX сделать это кажется

$ date -j -f "%FT%TZ" "2015-09-09T13:19:09Z"
Wed  9 Sep 2015 13:19:09 NZST

$ date -j -f "%FT%TZ" "2015-09-09T13:19:09Z"  +%s
1441761549

Выглядит нормально, за исключением того, что это неправильный ответ. Это ровно на 12 часов позади реального ответа и моего часового пояса +12, так как облачный часовой пояс влияет на эпоху unix?

И просто проверяю себя

$ docker run -it --rm trusty date -d"2015-09-09T13:19:09Z" +%s
1441804749

те же инструменты на linux дают правильный ответ ...

Я просто хочу понять, что здесь не так - я что-то упускаю или это просто сломанная вещь?

OSX Yosemite 10.10.4

UPD: Несколько дополнительных деталей - я бы предположил, что это разница между date util, за исключением того, что это не только date.

Stass-MacBook:~ void$ python -c 'import dateutil.parser; print dateutil.parser.parse("2015-09-09T13:19:09Z").strftime("%s")'
1441761549

Stass-MacBook:~ void$ docker run trusty python -c 'import dateutil.parser; print dateutil.parser.parse("2015-09-09T13:19:09Z").strftime("%s")'
1441804749

person flashvoid    schedule 11.09.2015    source источник


Ответы (1)


Короткий ответ заключается в том, что результат, который вы получаете, является ожидаемым и правильным, когда вы запускаете утилиту OS X BSD date с этими аргументами. Потому что он отличается от GNU date.

Для вывода, подобного этому, из GNU date, вам нужно добавить параметр --utc и запустить его следующим образом:

echo $(date --utc -d '2015-09-09T13:19:09Z' +"%a %-d %b %Y %H:%M:%S") $(date +%Z)

Если ваш часовой пояс установлен на NZST, то приведенное выше выдаст следующее:

Wed 9 Sep 2015 13:19:09 NZST

Концептуально этот вызов - это то, что вы можете представить, что BSD date запускается как date -j -f "%FT%TZ" "2015-09-09T13:19:09Z". Во-первых, даже если вы говорите, поместите эту дату / время в формат по умолчанию (и не меняйте его иначе), он все равно добавит туда часовой пояс.

Другой способ думать о том, что он делает, - это то, что по умолчанию BSD date работает так, как если бы вы указали эквивалент опции --utc, то есть, по сути, противоположность GNU date по умолчанию.

Другими словами, важное отличие BSD date -j -f состоит в том, что на самом деле это просто означает: взять эту строку в другом формате даты и просто поместить ее в формат даты по умолчанию, который мы здесь используем - без учета местного часового пояса вообще.

Тот факт, что BSD date в данном случае привязан к локальному часовому поясу, всегда казался мне по крайней мере чем-то вроде странной, сбивающей с толку причудой.

те же инструменты на linux дают правильный ответ ...

Я надеюсь, что из вышесказанного становится более ясным, что OS X date и Linux date на самом деле совсем не одни и те же инструменты, а вы, если вы ожидаете, что они будут вести себя одинаково, вы будете разочарованы ...


Что касается того, чтобы date в ваших сценариях вел себя одинаково на разных платформах, вы можете получить GNU date, используя homebrew для установки пакета coreutils:

brew install coreutils

Это сделает версию GNU доступной в вашей системе OS X под именем gdate. Таким образом, вы можете заменить date в своих сценариях на $DATECMD (или что-то в этом роде), а затем:

  • в среде OS X set DATECMD=gdate
  • в вашей среде Linux set DATECMD=date

Конечно, вместо этого вы можете просто сделать alias date=gdate, но это не рекомендуется, потому что иногда вам может понадобиться запустить сторонние инструменты, которые действительно ожидают BSD date в вашей среде.

person sideshowbarker    schedule 12.09.2015
comment
Обновил пост. Это было мое первое предположение, что просто date утилита отличается, но так получилось, что я пробовал разные утилиты, и все они давали одинаковый результат на OSX. Это где-то глубоко в какой-то библиотеке, что ли? - person flashvoid; 13.09.2015
comment
О python см. stackoverflow.com / questions / 24732872 / и stackoverflow.com / questions / 2335405 / О базовой библиотеке см. man strptime. Вы можете попробовать написать свое собственное простое приложение на C, используя strptime(3), и посмотреть, не изменится ли его поведение в OS X и в системе Linux. - person sideshowbarker; 13.09.2015