LoginSignup
2
0

More than 5 years have passed since last update.

1ラインでプレミアムフライデーを求めてみた

Last updated at Posted at 2017-11-07

とある業務システムでプレミアムフライデーに自動で割引を付けたいとのことで
今更ながらプレミアムフライデーを求める式を考えてみた。

巷によくあるのは、ループでぐるぐるするタイプが多い。
ソース読んでわかりやすいし、あとあとメンテも楽だろうけど
でもそれだと、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 456
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 234 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など一部言語では使用できないとのこと。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0