`date`コマンドにISO-8601メインフォーマット入力オプションがありませんか?

`date`コマンドにISO-8601メインフォーマット入力オプションがありませんか?

私は時々このdateコマンドを使用して、ISO-8601曜日カレンダーに基づいて現在または将来の日付の週番号を確認します。これを行うには、次のようにします。date +%V現在のISO週番号を確認し、date -d "2021-12-25" +%V他の日付(この場合はクリスマス)のISO週番号を確認します。

しかし、これを逆にすることは不可能に見えます。つまり、「週番号」形式の日付が与えられると、「月 - 日付」形式の日付が取得されます。たとえば、を実行すると、date -d "2021-W50-3"その形式がサポートされていないというエラーが発生します。なぜできないの?この形式を使用して日付を入力または保存する方法はありますか?

答え1

GNUにはdate非標準オプションがあり(およびオンライン-dで文書化されている)、限られた日付/時刻フォーマットセットのみをサポートしています。info date 'Date input formats'ここ)。

dateより多くの日付形式(参照する形式を含む)をサポートする実装では、from実装を使用できます(dateGNUなどのast-open入力日付でも機能します)。-ddate

(しかしそのような場合はほとんどありません)の一部として構築されている場合は、dateksh93シェルの組み込みである可能性があり、代わりに組み込みast-open(常に含まれています)と指定子(時間はありませんが、解析された部分はコピーされます)をdate使用できます。 :printf%Tbash

$ builtin date
$ date -d '2021-W50-3' +%F
2021-12-15
$ printf '%(%F)T\n' 2021-W50-3
2021-12-15

bashシェル(または他のシェル)では、いつでも次のことができます。

$ ksh93 -c '"${@:0}"' printf '%(%F)T\n' 2021-W50-3
2021-12-15

ただし、システムによっては、ksh93は呼び出されたり(またはSolaris 11 +のように、Thereとも呼ばれる)まったく呼び出されないことがありますkshksh2020ksh93 shksh例:bashまたはzsh)システムはデフォルトではインストールされません。すべてのシステムで。

参考にしてください。基準strftime()この標準形式の日付は、仕様および対応する標準%G-%V-%u機能に従って生成できます。分析するタイムスタンプ(strptime())はサポートも%Gサポート%Vもしません。標準UNIXgetdate())。

GNUはstrptime()現在、それを標準の拡張として理解していますが、無視するように文書化されています(参照info libc strptime)。FreeBSDstrptime()同じディレクティブがサポートされていると文書化されていますが、FreeBSD 12.2(組み込みstrftime()使用)のテストでは機能しないようです。zshstrftime -r

ただし、POSIX、GNU、およびfreebsdはstrptime()これをサポートしています%W

  • zsh:

    $ strftime -rs t %Y-W%W-%u 2021-W50-3 && strftime %F $t
    2021-12-15
    
  • busybox:

    $ busybox date -D %Y-W%W-%u -d 2021-W50-3 +%F
    2021-12-15
    

%Y-%W同じではありませんが、%G-%Vこの場合は偶然の一致です。%W1月1日は00で、月曜日の場合は01です。そして%V、(ISO週番号)は、その週の日数が前年または今年であるかどうかに応じて、その年の最初の週(01)または前年の最後の週(52または53)です。

答え2

正確なISO週の日付(前または次の年へのロールオーバーを含む)は、2つの実行を使用して取得できますdate。 1つは既知の日付(私は6月1日を選択しました)で補正し、もう1つはISO週/日の差を数値で調整します。仕事。これはうるう年の影響を受けません。これが月の代わりにISO週を使用することです。

この関数は、2021-W50-3形式を2021-12-15に変換し、年の反転を表示するテストを実行します。

#! /bin/bash

isoDate () {

    declare -a dR   #.. Required date
    declare -a dC   #.. Calibration date.
    printf 1>&2 '\nAsked %s\n' "${1}"   #debug
    IFS='-' read -a dR <<<"${1}"
    IFS='-' read -a dC <<<"$( date -d "${dR[0]}-06-01" '+%G-W%V-%u' )"
    dR[1]=${dR[1]#W}; dR[1]=${dR[1]#0}
    dC[1]=${dC[1]#W}; dC[1]=${dC[1]#0}
    declare Adj=$(( 7 * (${dR[1]} - ${dC[1]}) + ${dR[2]} - ${dC[2]} ))
    date -d "${dR[0]}-06-01 + ${Adj} days" '+%Y-%m-%d'
}

    Ymd=$( isoDate '2021-W50-3' )
    printf 'Found %s\n' "${Ymd}"
    date -d "${Ymd}" '+Check %G-W%V-%u'

    Ymd=$( isoDate '2020-W01-1' )
    printf 'Found %s\n' "${Ymd}"
    date -d "${Ymd}" '+Check %G-W%V-%u'

    Ymd=$( isoDate '2011-W52-7' )
    printf 'Found %s\n' "${Ymd}"
    date -d "${Ymd}" '+Check %G-W%V-%u'

結果:

$ ./isoDate

Asked 2021-W50-3
Found 2021-12-15
Check 2021-W50-3

Asked 2020-W01-1
Found 2019-12-30
Check 2020-W01-1

Asked 2011-W52-7
Found 2012-01-01
Check 2011-W52-7
$ 

関連情報