Вычтите время, используя дату и bash.

Я работаю над новой MPI платформой, но для этого сценария она не подойдет, потому что, насколько я понимаю, у вас много общей памяти.

Возможно, вам поможет openmp с многопоточностью для локального параллелизма, а согласно моему опыту, для параллелизма через сеть, OpenMPI является лучшим выбором и хорошо документирован для дистрибутивов linux.

P.S. Не могли бы вы подробнее описать требования к параллелизму?

19
30.01.2019, 12:22
5 ответов

Это работает правильно, если вы сначала конвертируете дату ввода в ISO 8601:

$ date -d "$(date -Iseconds -d "2018-12-10 00:00:00") - 5 hours - 20 minutes - 5 seconds"
So 9. Dez 18:39:55 CET 2018
7
27.01.2020, 19:44

Последний пример должен прояснить для вас:часовые пояса .

$ TZ=UTC date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_03:00:00
$ TZ=Asia/Colombo date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S 
2019-01-19_08:30:00

Поскольку выходные данные явно различаются в зависимости от часового пояса, я подозреваю, что -какое-то неочевидное значение по умолчанию используется для строки времени без указания часового пояса. Проверив пару значений, кажется, UTC -05 :00 , хотя я не уверен, что это такое.

$ TZ=UTC date -d "2019-01-19T05:00:00 - 2 hours" +%Y-%m-%d_%H:%M:%S%Z
2019-01-19_08:00:00UTC
$ TZ=UTC date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S%Z
2019-01-19_03:00:00UTC
$ TZ=UTC date -d "2019-01-19T05:00:00" +%Y-%m-%d_%H:%M:%S%Z           
2019-01-19_05:00:00UTC

Используется только при выполнении арифметических операций с датами.


Кажется, проблема здесь в том, что - 2 hours— это не , воспринимаемое как арифметическое, а как спецификатор часового пояса:

# TZ=UTC date -d "2019-01-19T05:00:00 - 2 hours" +%Y-%m-%d_%H:%M:%S%Z --debug
date: parsed datetime part: (Y-M-D) 2019-01-19 05:00:00 UTC-02
date: parsed relative part: +1 hour(s)
date: input timezone: parsed date/time string (-02)
date: using specified time as starting value: '05:00:00'
date: starting date/time: '(Y-M-D) 2019-01-19 05:00:00 TZ=-02'
date: '(Y-M-D) 2019-01-19 05:00:00 TZ=-02' = 1547881200 epoch-seconds
date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns),
date:     new time = 1547884800 epoch-seconds
date: timezone: TZ="UTC" environment value
date: final: 1547884800.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-01-19 08:00:00 (UTC)
date: final: (Y-M-D) 2019-01-19 08:00:00 (UTC+00)
2019-01-19_08:00:00UTC

Таким образом, мало того, что не выполняются никакие арифметические действия, кажется, летнее время корректировка времени на 1 час, что приводит к несколько бессмысленному времени для нас.

Это справедливо и для сложения:

# TZ=UTC date -d "2019-01-19T05:00:00 + 5:30 hours" +%Y-%m-%d_%H:%M:%S%Z --debug
date: parsed datetime part: (Y-M-D) 2019-01-19 05:00:00 UTC+05:30
date: parsed relative part: +1 hour(s)
date: input timezone: parsed date/time string (+05:30)
date: using specified time as starting value: '05:00:00'
date: starting date/time: '(Y-M-D) 2019-01-19 05:00:00 TZ=+05:30'
date: '(Y-M-D) 2019-01-19 05:00:00 TZ=+05:30' = 1547854200 epoch-seconds
date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns),
date:     new time = 1547857800 epoch-seconds
date: timezone: TZ="UTC" environment value
date: final: 1547857800.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-01-19 00:30:00 (UTC)
date: final: (Y-M-D) 2019-01-19 00:30:00 (UTC+00)
2019-01-19_00:30:00UTC

Еще немного отладки, синтаксический анализ выглядит следующим образом::2019-01-19T05:00:00 - 2(-2является часовым поясом )иhours(= 1 часу )с подразумеваемым добавлением. Становится легче увидеть, если вместо этого вы используете минуты :

.
# TZ=UTC date -d "2019-01-19T05:00:00 - 2 minutes" +%Y-%m-%d_%H:%M:%S%Z --debug
date: parsed datetime part: (Y-M-D) 2019-01-19 05:00:00 UTC-02
date: parsed relative part: +1 minutes
date: input timezone: parsed date/time string (-02)
date: using specified time as starting value: '05:00:00'
date: starting date/time: '(Y-M-D) 2019-01-19 05:00:00 TZ=-02'
date: '(Y-M-D) 2019-01-19 05:00:00 TZ=-02' = 1547881200 epoch-seconds
date: after time adjustment (+0 hours, +1 minutes, +0 seconds, +0 ns),
date:     new time = 1547881260 epoch-seconds
date: timezone: TZ="UTC" environment value
date: final: 1547881260.000000000 (epoch-seconds)
date: final: (Y-M-D) 2019-01-19 07:01:00 (UTC)
date: final: (Y-M-D) 2019-01-19 07:01:00 (UTC+00)
2019-01-19_07:01:00UTC

Итак, арифметика дат выполняется, но не та, которую мы просили. ¯\ (ツ )/¯

26
27.01.2020, 19:44

TLDR:Это не ошибка. Вы только что обнаружили одно из малозаметных, но задокументированных поведений date. При выполнении арифметических операций с временем с помощью dateиспользуйте независимый от часового пояса -формат (, например время Unix ), или внимательно прочитайте документацию, чтобы знать, как правильно использовать эту команду.


GNU dateиспользует ваши системные настройки (переменную окружения TZили, если она не установлена, системные значения по умолчанию )определяют часовой пояс обеих дат, подаваемых с опцией -d/ --date. и дата, указанная аргументом +format. Опция --dateтакже позволяет переопределить часовой пояс для собственного аргумента опции -, но не переопределяет часовой пояс +format. Вот в чем корень путаницы, ИМХО.

Учитывая, что мой часовой пояс UTC -6, сравните следующие команды:

$ date -d '1970-01-01 00:00:00' '+Normal: %F %T %:z%nUnix: %s'
Normal: 1970-01-01 00:00:00 -06:00
Unix: 21600
$ date -d '1970-01-01 00:00:00 UTC' '+Normal: %F %T %:z%nUnix: %s'
Normal: 1969-12-31 18:00:00 -06:00
Unix: 0
$ TZ='UTC0' date -d '1970-01-01 00:00:00 UTC' '+Normal: %F %T %:z%nUnix: %s'
Normal: 1970-01-01 00:00:00 +00:00
Unix: 0

Первый использует мой часовой пояс как для -d, так и для +format. Второй использует UTC для -d, но мой часовой пояс для +format. Третий использует UTC для обоих.

Теперь сравните следующие простые операции:

$ date -d '1970-01-01 00:00:00 UTC +1 day' '+Normal: %F %T %:z%nUnix: %s'
Normal: 1970-01-01 18:00:00 -06:00
Unix: 86400
$ TZ='UTC0' date -d '1970-01-01 00:00:00 UTC +1 day' '+Normal: %F %T %:z%nUnix: %s'
Normal: 1970-01-02 00:00:00 +00:00
Unix: 86400

Даже если время Unix говорит мне то же самое, «обычное» время отличается из-за моего собственного часового пояса.

Если бы я хотел выполнить ту же операцию, но используя исключительно свой часовой пояс:

$ TZ='CST+6' date -d '1970-01-01 00:00:00 -06:00 +1 day' '+Normal: %F %T %:z%nUnix: %s'
Normal: 1970-01-02 00:00:00 -06:00
Unix: 108000
5
27.01.2020, 19:44

GNU dateподдерживает простую арифметику дат, хотя расчеты времени эпохи, как показано в ответе @sudodus, иногда более ясны (и более переносимы ).

Использование +/ -при отсутствии часового пояса, указанного в метке времени, инициирует попытку сопоставить следующий часовой пояс, прежде чем что-либо еще будет проанализировано.

Вот один из способов сделать это: используйте «назад» вместо «-»:

$ date -d "2018-12-10 00:00:00 5 hours ago 20 minutes ago 5 seconds ago"
Sun Dec  9 18:39:55 GMT 2018

или

$ date -d "2018-12-10 00:00:00Z -5 hours -20 minutes -5 seconds"
Sun Dec  9 18:39:55 GMT 2018

(Хотя вы не можете произвольно использовать «Z», это работает в моей зоне, но это делает отметку времени зоны UTC/GMT -использовать вашу собственную зону или %z/%Z, добавляя ${TZ:-$(date +%z)}к отметке времени вместо.)

Добавление дополнительных временных условий для времени настройки этих форм:

  • "5 часов назад" вычесть 5 часов
  • "4 часа" добавить (неявно )4 часа
  • «через 3 часа» добавить (явный )3 часа (не поддерживается в более ранних версиях)

Можно использовать множество сложных корректировок в любом порядке, (хотя относительные и переменные термины, такие как «через 14 недель, начиная с прошлого понедельника», вызывают затруднения;-)

(Здесь тоже есть еще одна маленькая ловушка, dateвсегда будет давать правильную дату, поэтому date -d "2019-01-31 1 month"дает 2019 -03 -03, как и "в следующем месяце")

Учитывая большое разнообразие поддерживаемых форматов времени и даты, синтаксический анализ часового пояса неизбежно выполняется небрежно :это может быть однобуквенный или многобуквенный -суффикс, час или час :минутное смещение, имя " America/Denver" (или даже имя файла в случае переменной TZ).

Ваша версия 2018-12-10T00:00:00не работает, потому что "T" — это просто разделитель,не часовой пояс, добавление «Z» в конце делает эту работу (зависимой от правильности выбранной зоны ), как и ожидалось.

См. :https://www.gnu.org/software/tar/manual/html_node/Date-input-formats.htmlи, в частности, раздел 7.7.

6
27.01.2020, 19:44

Это решение простое для понимания, но немного более сложное, поэтому я показываю его в виде шелл-скрипта.

  • преобразовать в «секунды с 1970 года -01 -01 00 :00 :00 UTC»
  • добавить или вычесть разницу
  • преобразовать обратно в удобочитаемый формат с помощью окончательной dateкомандной строки

Шеллскрипт:

#!/bin/bash

startdate="2018-12-10 00:00:00"

ddif="0"          # days
diff="-5:-20:-5"  # hours:minutes:seconds

#-----------------------------------------------------------------------------

ss1970in=$(date -d "$startdate" "+%s")  # seconds since 1970-01-01 00:00:00 UTC
printf "%11s\n" "$ss1970in"

h=${diff%%:*}
m=${diff#*:}
m=${m%:*}
s=${diff##*:}
difs=$(( (((ddif*24+h)*60)+m)*60+s ))
printf "%11s\n" "$difs"

ss1970ut=$((ss1970in + difs))  # add/subtract the time difference
printf "%11s\n" "$ss1970ut"

date -d "@$ss1970ut" "+%Y-%m-%d %H:%M:%S"
1
27.01.2020, 19:44

Теги

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