如何检查日期时间是否存在于另一个日期时间内?

时间:2015-02-23 05:24:08

标签: ruby-on-rails ruby ruby-on-rails-3

我正在开发一个用于考试管理的Rails应用程序。

考试可以创建一段时间。

Exam模型包含字段start_date:datetimeend_date:datetime

考试创建是一个两步过程。在第一步中,我们会提供包括start_dateend_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"

怎么可能?

4 个答案:

答案 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)
相关问题