首页 > 解决方案 > 确定当前时间是否在时间范围内。如果没有找到下一个打开的窗口是什么

问题描述

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

一家企业可能有一套窗户周一至周五上午 10 点至下午 3 点、下午 6 点至晚上 11 点周六至周日上午 2 点至上午 6 点、下午 3 点至下午 4 点

这是一个样本

因此,一家企业每天可能有多个业务窗口,并且它们可能会在一周中的每一天有所不同。每个企业也将位于不同的时区,因此也必须考虑到这一点。

当一条消息进来传递时,我需要知道当前时间是否在一个窗口内。如果不是,它将排队,我需要在下一个打开的窗口中交付它。

我有点不知道从哪里开始以及如何开始这个。任何帮助,将不胜感激。抱歉,如果问题不够细化。

谢谢你。

标签: rubyruby-on-rails-4activerecord

解决方案


假设您要构造一个散列,其键是企业,值是窗口,窗口是一个由七个数组组成的数组,一个代表一周中的每一天:

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

每个每日窗口都是一系列形式的范围first_sec..last_secfirst_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对于星期一,making start_day = 2)。

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

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

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

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


推荐阅读