とある業務システムでプレミアムフライデーに自動で割引を付けたいとのことで
今更ながらプレミアムフライデーを求める式を考えてみた。
巷によくあるのは、ループでぐるぐるするタイプが多い。
ソース読んでわかりやすいし、あとあとメンテも楽だろうけど
でもそれだと、SQLやEXCELでわざわざストアドやマクロ書かないといけなくてちょっと使いにくい。
曜日はプログラムでは数値で表される、7進数だと考えると
カレンダーは曜日を表すとこんな感じに並べられている。
3 4 5 6
0 1 2 3 4 5 6
0 1 2 3 4 5 6
0 1 2 3 4 5 6
0 1 2 3 4
プレミアムフライデーを赤字にしてみるとこうなる
3 4 5 6
0 1 2 3 4 5 6
0 1 2 3 4 5 6
0 1 2 3 4
56
0 1 2 3 4
こうすると、月末から7日マイナス
して、
そこに金曜日マイナス月末の曜日
を足せば良さげに見える。
するとこんな式ができる
月末日 - 7 + (目標曜日 - 月末の曜日)
もし金曜日をあらわすのが 5 だったら
5 - 月末の曜日(4) = 1
なので、月末 マイナス 7日 + 1
すればいい
だがしかし、一見すると上手くいくように見えるが
別の世界線ではプレミアムウェンズデーかもしれない
その場合、水曜日を表すのが 3 だとすれば?
3 - 月末の曜日(4) = -1
この場合月末に マイナス7 すると 月末 - 8
となって最終水曜日ではなくなり、おかしなことになる。
3 4 5 6
0 1 2 3 4 5 6
0 1 2 3 4 5 6
0 1 2
34 5 6
0 1 2 3 4
つまり計算結果がマイナス7日を超えてしまうのが原因なのだ
ならば常に7で割った余り
を求めればいいのでは?
ピコーン
じゃあ、剰余 使ってみるか!
月末日 + ((目標曜日 - 月末の曜日 - 7) MOD 7)
mysql> SELECT DATE_ADD(LAST_DAY(CURRENT_DATE()), INTERVAL MOD(4 - WEEKDAY(LAST_DAY(CURRENT_DATE())) - 7, 7) DAY);
+----------------------------------------------------------------------------------------------------+
| DATE_ADD(LAST_DAY(CURRENT_DATE()), INTERVAL MOD(4 - WEEKDAY(LAST_DAY(CURRENT_DATE())) - 7, 7) DAY) |
+----------------------------------------------------------------------------------------------------+
| 2017-11-24 |
+----------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
おおお!行けてるっぽいぞ!
【追記】
この式は負の剰余を使うため、PerlやPythonなど一部言語では使用できないとのこと。