确定当前时间是否在时间范围内。如果找不到,则下一个打开的窗口是什么

时间:2018-11-12 15:58:10

标签: ruby ruby-on-rails-4 activerecord

我有一个应用程序,仅当它们在设置的消息窗口内时,才需要向他们发送消息。

一家企业可能在周一至周五上午10点至下午3点,下午6点至晚上11点有一组Windows                                        星期日2 am-6am,3 pm-4pm

这是一个样本

因此,一家公司每天可能有多个业务窗口,并且它们可能在一周中的每一天有所不同。每个业务还将处于不同的时区,因此也必须加以考虑。

当有邮件要发送时,我需要知道当前时间是否在窗口内。如果不是,它将排队,我需要在下一个打开的窗口中交付它。

我有点无所适从,从何处开始。任何帮助,将不胜感激。很抱歉,这个问题不够详细。

谢谢。

1 个答案:

答案 0 :(得分:0)

假设您要构造一个散列,其键是业务,其值是窗口,该窗口是由七个数组组成的数组,一个星期中的每一天:

windows = [sun_windows, mon_windows, ... , sat_windows]

每个每日窗口都是一组first_sec..last_secfirst_seclast_sec形式的范围,从午夜开始数秒。这些范围的排序方式是每个范围的结束(秒)小于下一个范围的开始。

例如,假设某个特定企业在星期一有两个窗口,8:00-12:0013: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,等于start_day = 2)。

请注意,如果仅在windows[start_day+i) % 7] #=> []i = 0..5)的windows[start_day+i) % 7].first #=> nil星期一营业,则该方法将返回

next_window(windows, 2)
  #[1, 28800..43200]

28800..43200是下周一的第一个窗口。

关于时区,使所有时间成为格林威治标准时间似乎最简单。