送信の予約機能で、現在時刻に最も近い10分単位の時間を取得したいことがあり、その計算方法が勉強になったので記載します。
例えば現在時刻が15:55なら16:00を取得したいという趣旨です。
作成したメソッド
def round_off(seconds = 60)
Time.at((to_f / seconds).ceil * seconds)
end
上記のようにメソッドを定義し、以下のように呼び出すことで実現できました。
Time.now.round_off(10.minutes)
# もし現在時刻が16:55なら、17:00の時刻が取得できます。
何をしているか
先輩に教えてもらいながら書いたのですが、理解するのに時間がかかったのでメモしておきます。
1.指定した秒数で割り算をし、切り上げる
(to_f/seconds).ceil
2.その数字にもう一度指定の秒数を掛ける
(to_f/seconds).ceil * seconds
上記をすることで、現在時刻に最も近い将来で、指定した秒数の倍数が取れます。
単に数字で考えるとわかりやすかったです。
# 100.0 / 3 = 33.33333
(100.0 / 3).ceil # => 34
(100.0 / 3).ceil * 3 #=> 102
# 102は、100より大きい数で最も小さい3の倍数
3.Time.zone.atの引数に計算した結果を渡す
Time.at((to_f / seconds).ceil * seconds)
ちなみに開発では、ActiveSupport::TimeWithZone
クラスを拡張してメソッド化して作成しました。