Предположим, вам нужно было создать хеш, ключи которого являются предприятиями, а значения - окнами, окна - это массив из семи массивов, по одному на каждый день недели:
windows = [sun_windows, mon_windows, ... , sat_windows]
Каждое ежедневное окномассив диапазонов вида first_sec..last_sec
, first_sec
и last_sec
, представляющих секунды с полуночи.Эти диапазоны упорядочены в том смысле, что конец каждого диапазона (в секундах) меньше начала следующего диапазона.
Предположим, например, что для определенного бизнеса в понедельник было два окна, 8:00-12:00
и 13:00-17:00
.Тогда
mon_windows = [8*3600..12*3600, 13*3600..17*3600]
#=> [28800..43200, 46800..61200]
Предположим, теперь кто-то хотел знать, были ли в данный момент [:mon, 44000]
в пределах окна для этого бизнеса.Для этой задачи мы могли бы использовать следующий метод:
def covered?(windows_today, secs)
windows_today.each do |r|
return [false, r] if r.begin > secs
return true if r.cover?(secs)
end
false
end
Поскольку понедельник - второй день недели (смещение 1), мы должны выполнить:
covered?(windows[1], 44000)
#=> [false, 46800..61200]
где:
windows_today = windows[1]
#=> [28800..43200, 46800..61200]
Существует три возможных возвращаемых значения этого метода.
true
: сообщение может быть доставлено немедленно; [false, r]
: сообщение не можетбыть доставленным немедленно, но может быть доставлено в течение (следующего) окна (диапазона) r
в тот же день;и false
: сообщение не может быть доставлено в тот же день.
В зависимости от требований, возможно, потребуется только r.begin
(46800
в примере) ввторой случай.
В этом примере 44000
находится за пределами окна понедельника, а следующее окно - это диапазон 46800..61200
того же дня.
Мы бы закончили, если бы false
не было возвращено.В этом случае нам нужно определить следующее окно.
def next_window(windows, start_day)
dow = 7.times.find { |i| windows[(start_day + i) % 7].any? }
dow = (start_day + dow) % 7
[dow, windows[dow].first]
end
, где start_day
равно 1
плюс номер текущего дня недели (например, 1
для понедельника, что составляет * 1053).*).
Обратите внимание: если бизнес открыт только в понедельник windows[start_day+i) % 7] #=> []
для i = 0..5
(т. Е. windows[start_day+i) % 7].first #=> nil
), а метод вернет
next_window(windows, 2)
#[1, 28800..43200]
28800..43200
Будучи первым окном следующего понедельника.
Что касается часовых поясов, казалось бы, что самое простое - сделать Гренвич по среднему времени.