私は時々この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実装を使用できます(date
GNUなどのast-open
入力日付でも機能します)。-d
date
(しかしそのような場合はほとんどありません)の一部として構築されている場合は、date
ksh93シェルの組み込みである可能性があり、代わりに組み込みast-open
(常に含まれています)と指定子(時間はありませんが、解析された部分はコピーされます)をdate
使用できます。 :printf
%T
bash
$ 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とも呼ばれる)まったく呼び出されないことがありますksh
。ksh2020
ksh93 sh
(ksh
例:bashまたはzsh)システムはデフォルトではインストールされません。すべてのシステムで。
参考にしてください。基準strftime()
この標準形式の日付は、仕様および対応する標準%G-%V-%u
機能に従って生成できます。分析するタイムスタンプ(strptime()
)はサポートも%G
サポート%V
もしません。標準UNIXgetdate()
)。
GNUはstrptime()
現在、それを標準の拡張として理解していますが、無視するように文書化されています(参照info libc strptime
)。FreeBSDstrptime()
同じディレクティブがサポートされていると文書化されていますが、FreeBSD 12.2(組み込みstrftime()
使用)のテストでは機能しないようです。zsh
strftime -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
この場合は偶然の一致です。%W
1月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
$