echo 20171231 | xargs -i date -d "{} +1 day" | xargs -i date -d "{} -1 month"
**Fri Dec 1 00:00:00 PST 2017**
この場合、日付書式設定コマンドをパイプすると12月1日になります。
echo 20171231 | xargs -i date -d "{} +1day -1 month"
Sat Dec 2 00:00:00 PST 2017
単一のデータコマンドに日付形式が含まれる場合、結果は12月2日です。
上記のコマンドでは、-1ヶ月が+1日より優先順位が高くなります。
誰かがこれがどのように機能するかを理解するのに役立ちますか?
答え1
いいえ、優先順位はありません。
date
皮肉なことに、この問題は今月Debianユーザーメーリングリストに突然現れました。誰かが人間が読むことができる自然言語日付操作コマンドを読む人には、GNUツールの動作は非常に一貫性がないように見えたと指摘しました。 Vincent Lefèvreは次の例を提供します。
jdebp % date+%Y-%m-%d -d '2003-02-01 - 1ヶ月' 2003-01-01 jdebp % date+%Y-%m-%d -d '2003-02-01 - 31日' 2003-01-01 jdebp % date+%Y-%m-%d -d '2003-02-01 - 31日 + 1ヶ月' 2003-01-29 jdebp % date+%Y-%m-%d -d '2003-02-01 - 1ヶ月 + 1ヶ月' 2003-02-01 jdebp % date+%Y-%m-%d -d '2003-09-01 1日前 + 1ヶ月' 2003-09-30 jdebp % date+%Y-%m-%d -d '2003-09-01 1日前' 2003-08-31 jdebp % date+%Y-%m-%d -d '2003-08-31 + 1ヶ月' 2003-10-01 精製量%
内部的に実際に起こるものは、計算date
中に負の値(例:2003-03-(-30)
再正規化これは、C標準ライブラリの関数を使用したすべての操作以降の無効な日付です。
これは何ですか?いいえ現在進行中の作業は再正規化です。あらゆる段階で、人間のように。したがって、2003-02-01から31日を引いた日付は、date
GNUプログラムに無効な日付です。2月30日否定的、人間的に可能な限り1月の有効な日付ではありません。月を追加すると、3月の無効な日付になり、まだマイナス30になります。もちろん、-30
ゼロより大きい数字に調整すると、2月全体に戻るため、1月の対応する日付に再正規化されます。他の例では、再正規化のない無効な日付は、2003-10-00
および2003-09-00
です2003-09-31
。
これをあなたの例に適用します。
2017-12-31 + 1 day
2017-12-32
はい、プログラム出力から。2018-01-01
2018-01-01 - 1 month
2018-00-01
はい、プログラム出力から。2017-12-01
2017-12-31 + 1 day - 1 month
2017-11-32
はい、プログラム出力から。2017-12-02
あなたが見たようにすべての段階で再正規化します。date
GNU は複数の変更を一度に適用するため、すべての変更を一度に適用するのと同じ結果は得られません。すべての段階で再正規化なし。
追加読書
- マイケルストーン(2013-11-21)。
/bin/date
: 一貫性のない日付の解析。 Debian のバグ #729952. - ウルフ・ジビス(2017-03-15)。 非生産的な計算順序
date
。 GNUのバグ#26101。 - ヴィンセント・ルペブル(2018-02-06)。「未修正」エラーラベルに関するポリシー。 Debian ユーザーです。
答え2
date
私が見るには、月が最初に返され、次の日付がその順序で追加されるようです。
パイプラインでジョブの順序を変更すると、他のジョブと同じ結果が得られます。
$ echo 20171231 | xargs -i date -d "{} -1 month" | xargs -i date -d "{} +1 day"
Sat Dec 2 00:00:00 EET 2017
問題は12月31日から一ヶ月前に戻るのが問題だということだ。先月同日は11月31日だったが、11月は30日しか残っていなかった。ある意味では、11月31日は12月1日と同じなので、後者を与える論理もあります。
もちろん、他のオプションは12月31日から11月30日までですが、完全に問題がないわけではありません。それではNov 30 - 1 month
、10月30日でなければならないのでしょうか、それとも10月31日でなければなりませんか?
必要なロジックを手動で実装する必要があるかもしれません。
答え3
この状況の理由は次のとおりです。
$ a=20171231; b=$(date -d "$a -1 month"); echo "<$b>"
<Fri Dec 1 00:00:00 PST 2017>
注文日が12月上旬に移動されました。
1日を追加するとdayになります2
。
代わりに1月1日になると1か月前に戻ります。
$ a=20180101; b=$(date -d "$a -1 month"); echo "<$b>"
<Fri Dec 1 00:00:00 PST 2017>
これは日付の内部特性です。
date
指定された日付と同じ前月の日付を返します。
$ a=20171110; b=$(date -d "$a -1 month"); echo "<$b>"
<Tue Oct 10 00:00:00 PST 2017>
つまり、11月に指定された日付は遡及し、10月に日付を指定することができます。しかし、もしその日が31日であれば問題が生じます。たとえば、10月31日から開始すると、9月31日がないため、10月1日に戻ります。
$ a=20171031; b=$(date -d "$a -1 month"); echo "<$b>"
<Sun Oct 1 00:00:00 AST 2017>
月の移動は、日付が01の場合にのみ正確です。 2月は特に奇数月です。
$ a=20170331; b=$(date -d "$a -1 month"); echo "<$b>"
<Fri Mar 3 00:00:00 AST 2017>
2月31日がないからです。