最近かかわったプロジェクトですごいなと思ったので残しておく
1週間のスケジュールを曜日ごと、さらに時間ごと,24時間でフラグを持たせて動作を変えたい時などに使う感じ
月水金曜日の13時にフラグをセット!みたいなことができる
DB上の一つのカラムにフラグ情報を持たせて保存する
000000ffffff000001ffffff000000ffffff000000
たったこれだけで一週間の中で1時間ごとのフラグ管理が出来てしまいます
cronより複雑なスケジューリングが出来たりする?
方法は簡単、16進数で扱ってビット演算を駆使するというもの
詳細
- times_in_hex
000000ffffff000001ffffff000000ffffff000000
42桁の文字列
16進数でフラグ管理
週単位
42桁を7等分する
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
0000000 | ffffff | 000001 | ffffff | 000000 | ffffff | 000000 |
区切ったそれぞれの値が曜日に割り当てられる
日単位
区切った単位でさらに詳細に分解していく
ffffff
6文字の文字列に対して考える
2進数に変換すると
f | f | f | f | f | f |
---|---|---|---|---|---|
1111 | 1111 | 1111 | 1111 | 1111 | 1111 |
となるので
4 * 6 = 24
ということで1時間ごとのフラグを管理できる(0 or 1)
時 | 1-4 | 5-8 | 9-12 | 13-16 | 17-20 | 21-24 |
---|---|---|---|---|---|---|
フラグ | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 |
16進数 | f | f | f | f | f | f |
こういう持ち方をすることで判定として16進数での1文字がFであれば対象の4時間はすべてチェックされているという判断もできたりする
時差について
cron実行時はUTC基準で判断している
ということはDBに入る値もUTC基準になっている
なので、格納時、表示時にTimezoneを考慮した変換をしなくてはならない
標準時からフラグ情報を時差分ずらす作業を行うことで扱うデータをすべてUTCにすることができる
週単位のフラグを管理しているからできる事だが...
日本を例に見てみる
月曜のみフラグが入っている設定の場合
000000 ffffff 000000 000000 000000 000000 000000
000000fffff000000000000000000000000000000
これを2進数に変換すると
0000000000000000000011111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
となる
1時間ごとに1文字なので9時間ずらす
utc = Time.now result = utc << 9
0000000000011111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
16進数に変換しなおすと
001FFFFE00000000000000000000000000000000
となり、保存する値は上記になる
168桁のフラグを16進数に凝縮して保存したという感じ
なるほどうまいなと思ったのと忘れない内に記録に残しておきます