EventBrigeのcron式のパーサ cronplan に以下のようなバグ報告があった。
github.com
5 10 31W * ? 2027の出力が cronplan とEventBridgeのコンソールで異なるとのこと。
Wはmonth-of-dayの末尾につけると、指定した日付が平日ではない場合、近い平日に寄せてくれる。
$ curl cronplan.in -d '5 10 31W * ? 2027'
Fri, 29 Jan 2027 10:05:00
Wed, 31 Mar 2027 10:05:00
Fri, 30 Apr 2027 10:05:00
Mon, 31 May 2027 10:05:00
Wed, 30 Jun 2027 10:05:00
Fri, 30 Jul 2027 10:05:00
Tue, 31 Aug 2027 10:05:00
Thu, 30 Sep 2027 10:05:00
Fri, 29 Oct 2027 10:05:00
Tue, 30 Nov 2027 10:05:00

ぱっと見た感じ31日のない月はスキップされているように見えるが、2027/10が表示されないのはおかしい。
% cal 10 2027
10月 2027
日 月 火 水 木 金 土
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
WはEventBridgeのcron式にいくつか存在するよくわからない仕様のやつで(ほかにはFRI#5の5週目の金曜日が存在しなかったらどうなるか、などがある)、コンソールの出力と、たぶん元になっていると思われるQuartzを参考にして実装した。
基本的には土曜日だったら金曜日に、日曜日だったら月曜日に寄せる動作になっているが、1日と月末は特殊で月が変わらないように日付を変更するようになる。
31Wの場合も同様に月が変わらないように変更していたが、その月に31日が存在しない場合はスキップされるという仕様を見落としていたようだった。
とりあえず、見落とした仕様に合わせて実装を直したが、コンソールで2027/10が無視されているのはよくわからない。
正直、コンソールのバグだと思っているが、2027年の10月になってみないと、実際に実行されるかわからない。
% curl cronplan.in -d '5 10 31W * ? 2027'
Fri, 29 Jan 2027 10:05:00
Wed, 31 Mar 2027 10:05:00
Mon, 31 May 2027 10:05:00
Fri, 30 Jul 2027 10:05:00
Tue, 31 Aug 2027 10:05:00
Fri, 29 Oct 2027 10:05:00
Fri, 31 Dec 2027 10:05:00
Quartzもバージョンによって31Wの動作が異なり、最新版の2.5.0ではcronplanと同じ動作だが、2.4.0ではなぜか Fri Apr 30 10:05:00 JST 2027が含まれる。
# quartz 2.4.0
# "0 5 10 31W * ? 2027"
Fri Jan 29 10:05:00 JST 2027
Wed Mar 31 10:05:00 JST 2027
Fri Apr 30 10:05:00 JST 2027 # <- ???
Mon May 31 10:05:00 JST 2027
Fri Jul 30 10:05:00 JST 2027
Tue Aug 31 10:05:00 JST 2027
Fri Oct 29 10:05:00 JST 2027
Fri Dec 31 10:05:00 JST 2027
ちなみに単に月の平日の最終日をスケジュールしたいならLWを使うのがよい。
% curl cronplan.in -d '5 10 LW * ? 2027'
Fri, 29 Jan 2027 10:05:00
Fri, 26 Feb 2027 10:05:00
Wed, 31 Mar 2027 10:05:00
Fri, 30 Apr 2027 10:05:00
Mon, 31 May 2027 10:05:00
Wed, 30 Jun 2027 10:05:00
Fri, 30 Jul 2027 10:05:00
Tue, 31 Aug 2027 10:05:00
Thu, 30 Sep 2027 10:05:00
Fri, 29 Oct 2027 10:05:00
