Этот скрипт перехватывает stdout и stderr и снова выводит их на stdout, если код выхода равен 0, и на stderr в противном случае.
Если строка содержит «ошибка :409 уже содержит версию», функция возвращает 0, а в противном случае исходный код выхода.
#!/bin/bash
function do_nuget ()
{
# save stdout and stderr
out=$(dotnet nuget push "$1" --source "$2" --api-key "$3" 2>&1)
exitcode=$?
# if out is not empty...
if [ -n "$out" ]; then
if [ $exitcode -eq 0 ]; then
# echo to stdout
echo "$out"
else
# echo to stderr
echo "$out" >&2
fi
fi
if [ "$out" != "${out/error: 409 already contains version}" ]; then
return 0
fi
return $exitcode
}
do_nuget "package.1.2.3.nupkg" "mysource" "mykey"
echo "got exit code: $?"
Вкратце :Дата, которую вы указываете с помощью --date
, берется по местному времени, если вы не укажете часовой пояс, и что-то вроде +/- NNN
принимается за единицу. Только все, что после этого, даже если это просто hour
, принимается как относительный модификатор. Таким образом, - 1 hour
означает не отнять один час от заданного времени, а указать, что время находится в часовом поясе UTC -01, а затем к добавить к нему один час.
То, что я думаю, должно работать для того, что вы пытаетесь, это либо явно указать часовой пояс перед смещением, либо поставить смещение первым , чтобы его нельзя было спутать с часовым поясом.
Здесь используется часовой пояс Центральноевропейского летнего времени (CEST )и сегодняшняя дата с добавлением %Z
к выходным данным для отображения часового пояса. (Вы также можете использовать %z
для вывода числового часового пояса или здесь +0200
.)
$ date +'%F %T %Z' -d '2021-04-19 12:00:00 CEST + 5 hours'
2021-04-19 17:00:00 CEST
$ date +'%F %T %Z' -d '+ 5 hours 2021-04-19 12:00:00'
2021-04-19 17:00:00 CEST
Хотя, конечно, для январской даты, как в вопросе, летний -часовой пояс, такой как CEST, не будет допустимым. Но перестановка двух по-прежнему работает, время, которое вы указываете, просто принимается за местное время в это время.
$ date +'%F %T %Z' -d '+ 5 hours 2021-01-01 12:00:00'
2021-01-01 17:00:00 CET
(А для 2021-10-31 02:30:00
я получаю CET, хотя это время также существует в CEST...)
(См. старые версии этого ответа для получения дополнительных примеров того, как он интерпретирует различные входные данные.)
Согласно ответу @muru на другой вопрос , мы также можем использовать опцию --debug
, чтобы программа действительно сообщала нам, что она сделала. Обратите внимание на вторую и третью строки:
$ date --debug +'%F %T %Z' -d '2021-04-19 12:00:00 - 1 hour' date: parsed date part: (Y-M-D) 2021-04-19 date: parsed time part: 12:00:00 TZ=-01:00 date: parsed relative part: +1 hour(s) date: input timezone: -01:00 (set from parsed date/time string) date: using specified time as starting value: '12:00:00' date: starting date/time: '(Y-M-D) 2021-04-19 12:00:00 TZ=-01:00' date: '(Y-M-D) 2021-04-19 12:00:00 TZ=-01:00' = 1618837200 epoch-seconds date: after time adjustment (+1 hours, +0 minutes, +0 seconds, +0 ns), date: new time = 1618840800 epoch-seconds date: output timezone: +01:00 (set from TZ="Europe/Berlin" environment value) date: final: 1618840800.000000000 (epoch-seconds) date: final: (Y-M-D) 2021-04-19 14:00:00 (UTC0) date: final: (Y-M-D) 2021-04-19 16:00:00 (output timezone TZ=+01:00) 2021-04-19 16:00:00 CEST
В справочной странице говорится:
The date string format is more complex than is easily documented here [...]
Что действительно кажется вполне уместным. Более полная документация находится на информационных страницах или в Интернете :https://www.gnu.org/software/coreutils/manual/html_node/Date-input-formats.html
.Да, когда значение -d простое, его эффект можно легко понять.
Да, -d '- 1 hour'
сместит время на 1 час назад.
$ date ; date -d '- 1 hour'
Mon 19 Apr 2021 07:58:52 AM EDT
Mon 19 Apr 2021 06:58:52 AM EDT
Строка, которую генерирует date
, указывает "момент времени".
По умолчанию этот «момент времени» записывается по местному времени. Но это также может быть записано в UTC0:
$ date ; date -u
Mon 19 Apr 2021 12:43:04 PM WAT
Mon 19 Apr 2021 11:43:04 AM UTC
Предположим, что ваше местное время – WAT -Западноафриканское время (WAT ).
Разумеется, такой же «момент времени» мог произойти и в других часовых поясах:
$ TZ=Asia/Kolkata date -d "Mon 19 Apr 2021 12:43:04 PM WAT"
Mon 19 Apr 2021 05:13:04 PM IST
Обратите внимание, что внутри значения -d
находится именно та дата, которая напечатана выше.
Это означает, что «момент времени» является полным только тогда, когда включен часовой пояс.
Вот почему рекомендуется печатать даты с добавлением %z
или %Z
. Формат %F %R
в этом смысле неполный, лучше использовать +'%F %R %z'
.
Когда вы использовали дату 2000/1/2 03:04:05
, вы не указали часовой пояс.
Вот почему команда date
принимает следующий - 1
за часовой пояс :
$ date -u -d '2000/1/2 03:04:05'; date -u -d '2000/1/2 03:04:05 - 1'
Sun 02 Jan 2000 03:04:05 AM WAT
Sun 02 Jan 2000 05:04:05 AM WAT
Это предполагает, что ваше местное время — WAT (и не меняется на летнее время, без летнего времени ). Я не могу сказать, так как вы не использовали ни %z
, ни %Z
. Изменение часового пояса изменило значение -d
с+1
(WAT )на -1
, разница в два часа.
Кроме того, вы написали hour
после этого, что это дополнительный час:
$ date -d '2000/1/2 03:04:05'; date -d '2000/1/2 03:04:05 - 1 hour'
Sun 02 Jan 2000 03:04:05 AM WAT
Sun 02 Jan 2000 06:04:05 AM WAT
Подтверждаю результаты.
И, наконец, +1:
$ date -d '2000/1/2 03:04:05 - 1 hour'; date -d '2000/1/2 03:04:05 + 1 hour ago'
Sun 02 Jan 2000 06:04:05 AM WAT
Sun 02 Jan 2000 02:04:05 AM WAT
+1
не изменяет значение времени (, как в WAT, или +1,уже ), но hour ago
сдвигает время на 1 час назад (с 3 на 2 ).
Поместите часовой пояс в значение времени -d
.
Или поставьте сначала относительную часть- 1 hour
$ date -d '2000/1/2 03:04:05 +0100 - 1 hour'
Sun 02 Jan 2000 02:04:05 AM WAT
$ date -d '-1 hour 2000/1/2 03:04:05'
Sun 02 Jan 2000 02:04:05 AM WAT
Многие другие инструменты обработки даты выполняют синтаксический анализ и арифметику даты как отдельные этапы. Например, с Perl:
perl -sE '
use Time::Piece;
use Time::Seconds;
$t = Time::Piece->strptime($timestamp, $format);
say $t->cdate;
$s = $t + ONE_HOUR;
say $s->cdate;
$s = $t - ONE_HOUR;
say $s->cdate;
' -- -timestamp='2000/1/2 03:04:05' -format='%Y/%m/%d %T'
Sun Jan 2 03:04:05 2000
Sun Jan 2 04:04:05 2000
Sun Jan 2 02:04:05 2000