我正在开发一个用于考试管理的Rails应用程序。
考试可以创建一段时间。
Exam
模型包含字段start_date:datetime
和end_date:datetime
考试创建是一个两步过程。在第一步中,我们会提供包括start_date
和end_date
在内的所有考试详情。
在第二步中,我想列出所有与当前考试时间段相冲突的考试,以便用户可以选择是否继续。
示例:
目前的考试:
Start date and time: "2015-02-23 10:30:00"
End date and time: "2015-02-23 13:30:00"
冲突考试:
Start date and time: "2015-02-23 12:30:00"
End date and time: "2015-02-23 14:30:00"
怎么可能?
答案 0 :(得分:1)
检查是否存在冲突最简单,然后以!
开头。显然,如果一个考试在另一个考试结束后开始,或者在另一个考试结束之前结束,那么就没有冲突。
我认为如果一次考试在另一次考试开始的同时开始没有冲突,但如果这被认为是冲突,那么这是一个简单的改变。我还假设没有时间旅行(即考试在开始之前结束)。
require 'time'
def conflict?(exam1, exam2)
!(Time.parse(exam1.last) <= Time.parse(exam2.first) ||
Time.parse(exam1.first) >= Time.parse(exam2.last))
end
conflict?(["2015-02-23 10:30:00", "2015-02-23 13:30:00"],
["2015-02-23 12:30:00", "2015-02-23 14:30:00"])
#=> true
conflict?(["2015-02-23 10:30:00", "2015-02-23 13:30:00"],
["2015-02-23 12:30:00", "2015-02-23 13:30:00"])
#=> true
conflict?(["2015-02-23 10:30:00", "2015-02-23 12:30:00"],
["2015-02-23 12:30:00", "2015-02-23 13:30:00"])
#=> false
conflict?(["2015-02-23 10:30:00", "2015-02-23 12:30:00"],
["2015-02-24 12:30:00", "2015-02-24 13:30:00"])
#=> false
编辑来考虑它,因为采用了日期 - 时间字符串格式,因此无需解析字符串。例如:
"2015-02-23 10:30:00" <= "2015-02-23 12:30:00"
#=> true
我们有:
def conflict?(exam1, exam2)
!(exam1.last <= exam2.first || exam1.first >= exam2.last)
end
conflict?(["2015-02-23 10:30:00", "2015-02-23 13:30:00"],
["2015-02-23 12:30:00", "2015-02-23 14:30:00"])
#=> true
conflict?(["2015-02-23 10:30:00", "2015-02-23 12:30:00"],
["2015-02-23 12:30:00", "2015-02-23 13:30:00"])
#=> false
答案 1 :(得分:0)
试试这个,通过其他考试conf
对象to overlaps
方法。它将返回冲突的检查对象数组
conf_array = []
def overlaps(conf)
conf_array << conf if (start_date - conf.end_date) * (conf.start_date - end_date) >= 0
end
或
conf_array = []
def overlaps(conf)
conf_array << conf if ((start_date..end_date).cover?(conf.start_date) || (start_date..end_date).cover?(conf.end_date))
end
或
conf_array = []
def overlaps(conf)
conf_array << conf if ((start_date..end_date).include_with_range?conf.start_date || (start_date..end_date).include_with_range?conf.end_date )
end
答案 2 :(得分:0)
如何创建名为 exam_time_range
的属性def exam_time_range
start_date..end_date
end
另一种检查冲突的方法
def time_conflict?(time)
exam_time_range.cover?(time) || time.cover?(exam_time_range)
end
最后但并非最不重要的是,保存逻辑的方法
def list_all_conflicts
Exam.find_each do |exam|
if time_conflict?(exam.start_date..exam.end_date)
exam
end
end
end
答案 3 :(得分:0)
为什么不在单个AR查询中执行此操作?像下面这样的东西,但它绝对可以写得更优雅。
# whatever u want
e = Exam.first
# Where start between e.start , e.end
# Or end between e.start , e.end
# And != e
Exam.where('start_date between datetime(?) and datetime(?)
OR end_date between datetime(?) and datetime(?)',
e.start_date, e.end_date, e.start_date, e.end_date)
.where.not(id: e.id)