解決策

解決策

GNU Dateは、現在の日付から時間を減算すると直感的に機能します。

date '+%F %R'; date '+%F %R' --date='- 1 hour'
2021-04-19 15:35
2021-04-19 14:35

ただし、日付をオペランドとして使用すると、結果が予期しない結果になります。

$ date '+%F %R' --date='2000/1/2 03:04:05 - 1 hour'
2000-01-02 06:04

$ date '+%F %R' --date='2000/1/2 03:04:05 + 1 hour ago'
2000-01-02 02:04

dateこの表現をどのように解釈する必要がありますか$date - 1 hour

答え1

簡単に言えば、--dateタイムゾーンを指定しないと、指定した日付は現地時間になり、同様の日付はタイムゾーン+/- NNNとして処理されます。それ以降は、hour単に相対修飾語として扱われても同じです。したがって、- 1 hour指定された時間から1時間を減算するのではなく、UTC-01時間帯に時間を指定します。次へ追加1時間で十分です。


私はそれがあなたが試していることに効果があると思います。オフセットの前にタイムゾーンを明示的に提供するか、オフセットを配置する必要があります。最初したがって、タイムゾーンと混同することはできません。

ここでは、中央ヨーロッパ夏時間帯(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

もちろん、問題の1月の日付にはCESTなどの夏のタイムゾーンは無効です。しかし、2つを並べ替えることはまだ機能し、提供する時間はその時間の現地時間と同じです。

$ 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:00CETにもその時間があったにもかかわらずCETを受けたので...)

(望むより旧バージョンさまざまな入力を解釈する方法の追加例については、この回答をご覧ください。 )


~によると他の質問に対する@muruの答え--debugまた、このオプションを使用して、プログラムが実際に行ったことを知らせるようにすることもできます。 2行目と3行目を参照してください。

$ date --debug +'%F %T %Z' -d '2021-04-19 12:00:00 - 1時間'
日付: 解析された日付部分: (YMD) 2021-04-19
日付:解析時間部分: 12:00:00 TZ=-01:00
日付:関連部分解析: +1時間
日付:入力時間帯:-01:00(構文解析された日付/時刻文字列で設定)
日付: 指定された時間を開始値として使用: '12:00:00'
日付: 開始日時: '(YMD) 2021-04-19 12:00:00 TZ=-01:00'
日付: '(YMD) 2021-04-19 12:00:00 TZ=-01:00' = 1618837200 epoch 秒
日付:調整された時間(+1時間、+0分、+0秒、+0ナノ秒)、
日付: 新しい時間 = 1618840800 epoch 秒
日付: 出力タイムゾーン: +01:00 (TZ="Europe/Berlin" 環境値で設定)
日付:最終:1618840800.000000000(エポック秒)
日付: 最終: (YMD) 2021-04-19 14:00:00 (UTC0)
日付: 最終: (YMD) 2021-04-19 16:00:00 (出力タイムゾーン TZ=+01:00)
2021-04-19 16:00:00 中央ヨーロッパサマータイム

マニュアルページには次のように記載されています。

日付文字列形式は、ここで簡単に文書化できるよりも複雑です[...]

これが適切に見えます。より包括的な文書は情報ページまたはオンラインにあります。https://www.gnu.org/software/coreutils/manual/html_node/Date-input-formats.html

答え2

-D

はい、-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(DSTのために変更されず、夏時間が適用されない)と仮定します。%zNorを使用しないので申し訳ありません%Z。タイムゾーンを変更すると、-d値は+1(WAT)から-12時間の差に変わります。

また、hourその後、さらに1時間かかったと書いた。

$ 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時間は変更されます。11時間前(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

答え3

他の多くの日付処理ツールは、解析と日付演算を別々のステップとして実行します。 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

関連情報