日付とbashを使用して時間を減算する

日付とbashを使用して時間を減算する

SEネットワークの他のすべての質問にはnow尋ねる)または日付のみを指定する場合(尋ねる)。

私が望むのは、日付と時刻を提供してからそこから時間を引くことです。
これが私が最初に試したことです。

date -d "2018-12-10 00:00:00 - 5 hours - 20 minutes - 5 seconds"

結果は2018-12-10 06:39:55- 7時間が追加されました。その後、20:05分を引いてください。

maninfoページを読んだ後、date問題を解決したようです。

date -d "2018-12-10T00:00:00 - 5 hours - 20 minutes - 5 seconds"

しかし、結果は同じです。 7時間はどこから来ますか?

その日、ユンチョが7200秒かもしれないと思って、他の日付も試してみましたが、ハハ。しかし、結果は同じです。

以下はいくつかの追加例です。

$ date -d "2018-12-16T00:00:00 - 24 hours" +%Y-%m-%d_%H:%M:%S
2018-12-17_02:00:00

$ date -d "2019-01-19T05:00:00 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-19_08:55:00

しかし、ここで状況は興味深いです。入力時間を省略すると正常に動作します。

$ date -d "2018-12-16 - 24 hours" +%Y-%m-%d_%H:%M:%S
2018-12-15_00:00:00

$ date -d "2019-01-19 - 2 hours - 5 minutes" +%Y-%m-%d_%H:%M:%S
2019-01-18_21:55:00

$ date --version
date (GNU coreutils) 8.30

私は何を見逃していますか?

修正する:Z最後に1つを追加し、動作が変更されました。

$ date -d "2019-01-19T05:00:00Z - 2 hours" +%Y-%m-%d_%H:%M:%S
2019-01-19_04:00:00

しかし、私はまだ混乱しています。この地域にはあまりありません。GNU情報ページ日付について。

時間帯の問題のようですが、引用するとカレンダー Wiki存在するISO 8601:

時刻表現とともに UTC 関係情報が提供されない場合、時刻は現地時間とみなされます。

これが私が望むものです。現地時間も正しく設定されています。日付/時刻を提供し、それから何かを取り除こうとする簡単な場合に、日付がタイムゾーンと混同される理由が何であるかよくわかりません。まず、日付文字列から時間を減らしてはいけませんか?まず日付に変換してから減算しても減算を省略すると、目的の結果が得られます。

$ date -d "2019-01-19T05:00:00" +%Y-%m-%d_%H:%M:%S
2019-01-19_05:00:00

だからもしこれは実際にはタイムゾーンの問題です。この狂気はどこから来るのですか?

答え1

この最後の例では、次のことを明確にしました。タイムゾーン

$ 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= 1時間)で暗黙的に追加されます。代わりに分を使用すると、確認する方が簡単です。-2hours

# 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

したがって、日付算術が行われていますが、私たちが要求したわけではありません。  ̄\(ツ)/ ̄

答え2

入力日を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

答え3

GNUはdate単純な日付算術をサポートしていますが、@sudodusの答えに示されている新起源の時間計算は時々よりきれいで移植性があります。

タイムスタンプにタイムゾーンが指定されていない場合、+ / -を使用すると、他のコンテンツを解析する前にタイムゾーンを一致させる試みがトリガされます。

「-」の代わりに「ago」を使用してこれを行う方法は次のとおりです。

$ 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ゾーンのタイムスタンプになります。独自のゾーンを使用するか、タイムスタンプに追加して${TZ:-$(date +%z)}%z / % Zを置き換えます。)

時間を調整するには、次の形式の追加の時間項目を追加します。

  • 「5時間前」 - 5時間
  • 「4時間」は(暗黙的に)4時間を加えます。
  • 「3時間後」は(明示的に)3時間を追加します(以前のバージョンではサポートされていません)。

任意の順序で多くの複雑な調整を使用できます(「先月曜日から14週間」などの相対的で可変的な用語は問題を引き起こしますが;-)

(ここに別の問題がありdateますdate -d "2019-01-31 1 month".

サポートされている時間と日付の形式が異なるため、タイムゾーンの解析は必然的に混乱します。単一文字または複数文字のサフィックス、時間または時:分オフセット、名前「America/Denver」(またはファイル名)です。変数からTZ)。

「T」は区切り文字だけでタイムゾーンではないため、バージョン2018-12-10T00:00:00は機能しません。最後に「Z」を追加すると、期待どおりに機能します(選択したゾーンの精度によって異なります)。

望むより: https://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html 特にセクション7.7。

答え4

この解決策はわかりやすいですが、少し複雑なので、シェルスクリプトとして表示します。

  • 「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"

関連情報