ruby-on-rails - How to compre DateTime with generic times in ruby
问题描述
I'm working on a ruby on rails app that can automatically schedule events. Every event has a start_time
datetime and an end_time
datetime.
Here is the problem:
In general, events shouldn't be scheduled before 9:00am or after 10:30pm. This is true for edge cases as well. I.e, even if an event ends after 9:00am, it shouldn't start before it. Similarly, if an event starts before 10:30pm, it should not go on passed 10:30pm.
How can I go about making sure that every event fits this criteria, when some of these events are on different dates?
The problem i'm having is that, yes, a DateTime object has a date and a time associated with it. But so does a Time object.
This means that if I have an event with a start and end datetime between 9am and 10:30pm, my comparison will always return false if I'm comparing a time object with a datetime object of a different date.
Here is what I had in mind:
def event_out_of_bounds?(event_start_time, event_end_time, min_start_time, max_end_time)
if event_start_time.hour > max_end_time.hour then
return true
end
if event_end_time.hour > max_end_time.hour then
return true
end
if event_start_time.hour < min_start_time.hour then
return true
end
if event_end_time.hour < min_start_time.hour then
return true
end
return false
end
Problems with this code:
- It doesn't take into account minutes. I.e., if I ever change
min_start_time
to 9:30 am, then this method won't work anymore. - There are different dates involved.
event_start_time
andevent_end_time
, which are DateTimes, obviously have the same date. However,min_start_time
andmax_end_time
, Which are created using Time.new have a different date (I just default it2020-01-01
). This wouldn't be a big problem if I knew beforehand what the dates would be for the events, however I won't in this case.
Any ideas for an algorithm to make this check elegantly?
解决方案
活动不应安排在上午 9:00 之前或晚上 10:30 之后。
我可能会用Range#cover?
这个。
require 'active_support/all'
def validate_schedule(s, e)
min = s.time_zone.local(s.year, s.month, s.day, 9, 0, 0)
max = s.time_zone.local(s.year, s.month, s.day, 22, 30, 0)
(min..max).cover?(s..e)
end
# Tests
et = ActiveSupport::TimeZone.new('Eastern Time (US & Canada)')
t = ->(d, h, m) { et.local(2020, 2, d, h, m, 0) }
test = ->(s, e) { puts format('%s %s = %s', s, e, validate_schedule(s, e)) }
test[t[1, 8, 59], t[1, 22, 30]] # false, start too early
test[t[1, 9, 0], t[1, 22, 30]] # true, 10:30 pm ok
test[t[1, 9, 0], t[1, 21, 30]] # true, 9:30 pm also ok
test[t[1, 9, 0], t[1, 22, 31]] # false, end too late
test[t[1, 9, 0], t[2, 22, 30]] # false, no all night parties
如果您允许多日活动,只需max
从结束日期 ( e
) 开始计算:
max = e.time_zone.local(e.year, e.month, e.day, 22, 30, 0)
Range.cover?
适用于“可以使用<=>
运算符比较的任何对象”。(请参阅范围中的自定义对象
推荐阅读
- python - 如何通过限制每个字符可以出现的次数来过滤字符串?
- sed - SED命令如下
- css - 定制器 css 值中的选择性刷新不起作用
- python - 如何修复python中的sklearn多元线性回归ValueError(样本数量不一致:[2, 1])
- java - 如何使用模拟答案从模拟方法修改 void 方法的输入参数
- c# - 在 C# 中使用 get;set 语句排除大于或小于的值
- java - 加载外部 Jar(插件架构)时 JavaFX 样式丢失
- firebase - Firebase 查询下载整个数据库。为什么?
- html - 如何扩展此表以填充页面?
- python - 如何从字符串中提取元组?