notebook

都内でWEB系エンジニアやってます。

16進数でフラグを管理する

最近かかわったプロジェクトですごいなと思ったので残しておく

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進数に凝縮して保存したという感じ

なるほどうまいなと思ったのと忘れない内に記録に残しておきます