次の形式のレコードを含むファイルがあります。
D20220327,S2927,977,1
D20220328,S2927,977,1
D20220329,S2927,977,1
D20220330,S2927,977,1
D20220331,S2927,977,1
D20220401,S2927,977,1
D20220402,S2927,977,1
D20220403,S2927,977,1
D20220404,S2927,977,1
ただし、この時間を過去7日前に移動する変換を適用した後、3月28日から4月3日までの日付には機能しませんが、同じコードロジックは3月27日と4月4日にはうまく機能します。なぜ一週間だけ働かないのかわかりません。これが出力です
D20220320,S2927,977,1 -- correct
D20220320,S2927,977,1 -- incorrect
D20220321,S2927,977,1 -- incorrect
D20220322,S2927,977,1 -- incorrect
D20220323,S2927,977,1 -- incorrect
D20220324,S2927,977,1 -- incorrect
D20220325,S2927,977,1 -- incorrect
D20220326,S2927,977,1 -- incorrect
D20220328,S2927,977,1 -- correct
ここで使用されるロジックは次のとおりです。
BEGIN {
OFS = FS = ","
}
{
t = mktime(sprintf("%4d %.2d %.2d 00 00 00",
substr($1,2,4),
substr($1,6,2),
substr($1,8,2)));
$1 = substr($1,1,1) strftime("%Y%m%d", t - 7*24*60*60)
print
}
答え1
あなたの計算は現地時間で行われ、3月27日の夏時間の移行の影響を受けます。
計算にUTC時間を使用するには(Unixタイムスタンプは現地時間ではありません)、最新バージョンのGNUを使用して追加の引数をawk
最後1
の引数として渡す必要がありますmktime()
。
t = mktime(sprintf("%4d %.2d %.2d 00 00 00",
substr($1,2,4),
substr($1,6,2),
substr($1,8,2)), 1);
これはGNUバージョン4.2.0+awk
で利用可能なGNU拡張です。awk
あるいは、真夜中(UTC)の周囲時間を参照時間として使用しないことがあります。
t = mktime(sprintf("%4d %.2d %.2d 12 00 00",
substr($1,2,4),
substr($1,6,2),
substr($1,8,2)));
これにより、以前のGNU実装と必要な機能を備えた他の実装awk
で機能することができます。awk
別のオプションは、変更されたローカルタイムゾーンでスクリプトを実行することです。
TZ=UTC awk -f script.awk inputfile
これにより、実行スクリプトにTZ
環境変数が設定され、関連機能で使用されるタイムゾーンが変更されます。UTC
awk
mktime()
答え2
Raku(以前のPerl_6)の使用
raku -pe 's/^ D <( (\d**4)(\d**2)(\d**2) )> \, /{ "$0-$1-$2".Date.earlier(:7days).Str.subst("-", :g); }/;'
入力例(空白行を削除):
D20220327,S2927,977,1
D20220328,S2927,977,1
D20220329,S2927,977,1
D20220330,S2927,977,1
D20220331,S2927,977,1
D20220401,S2927,977,1
D20220402,S2927,977,1
D20220403,S2927,977,1
D20220404,S2927,977,1
出力例:
D20220320,S2927,977,1
D20220321,S2927,977,1
D20220322,S2927,977,1
D20220323,S2927,977,1
D20220324,S2927,977,1
D20220325,S2927,977,1
D20220326,S2927,977,1
D20220327,S2927,977,1
D20220328,S2927,977,1
簡単に言えば、Rakuの1行ずつ(自動印刷)-pe
フラグはおなじみの演算子で使用されますs///
。数字は括弧付きの一致変数、およびにキャプチャされ、$0
キャプチャマーカーは一致$1
の他のすべての要素を削除するために使用されます。$2
<( … )>
代わりに、Rakuは{ … }
ブロック内でコードを実行します。 、およびキャプチャは適切なダッシュ()で文字列化され、文字列はメソッドを呼び出すことができるオブジェクトとして認識されます$0
。 [注:一部のユーザーは、より使い慣れた構文を書くことを見つけるかもしれません。どちらの形式も有効です。]オブジェクトが7日にリセットされると、記号で表示され、戻り時にダッシュ()を削除するために使用されます。$1
$2
-
Date
earlier(:7days)
earlier(days => 7)
Date
Str
subst
-
https://docs.raku.org/routine/Date
https://docs.raku.org/routine/Dateish
https://raku.org