简体   繁体   English

检查一个时间范围是否在另一个时间范围和Ruby on Rails多少小时之间

[英]Check if a time range is between another time range and how many hours Ruby on Rails

So I have a start_time and end_time. 所以我有一个start_time和end_time。 Which is maximum 24 hours. 最多24小时。 I guess I firstly need to check if this timerange is within another timerange say 21:00-01:00. 我想我首先需要检查此时间范围是否在另一个时间范围内,例如21:00-01:00。 If it is I need to know how many of the hours is within the timerange. 如果是,我需要知道在时间范围内有多少小时。 Any ideas? 有任何想法吗?

Use ((two- one) / 3600).round 使用((二合一)/ 3600).round

for example 例如

one=Time.now #=>2019-01-23 21:19:19 +0530
two=Time.now + 1*60*60 #=>2019-01-23 22:19:27 +0530
((two- one) / 3600).round #=>1 

difference is 1 hour for two different Time instance. 两个不同的Time实例的时差是1小时。

I assume the four arguments of the method below are strings of the form "HH:MM" or "HH:MM:SS". 我假设以下方法的四个参数是形式为“ HH:MM”或“ HH:MM:SS”的字符串。 I have provided a pure-Ruby solution that makes string comparisons only (for example: "17:26" < "18:00" #=> true ). 我提供了一个仅对字符串进行比较的纯Ruby解决方案(例如: "17:26" < "18:00" #=> true )。 That is, I do not convert the strings to Time objects. 也就是说,我不会将字符串转换为Time对象。

def time_within_ref?(time_start, time_end, ref_start, ref_end)
  (time_start >= ref_start) &&
  (adj_hour(time_start, time_end) <= adj_hour(ref_start, ref_end))
end

def adj_hour(start_str, end_str)
  end_str[0,2] = (end_str[0,2].to_i + 24).to_s if end_str < start_str
  end_str
end

Here are a few examples. 这里有一些例子。

time_within_ref?("19:00", "02:00", "18:00", "03:00")
  #=> true 
time_within_ref?("19:00", "04:00", "18:00", "03:00")
  #=> false
time_within_ref?("17:00", "02:00", "18:00", "03:00")
  #=> false
time_within_ref?("18:00", "02:00", "18:00", "03:00")
  #=> true

What do you mean by "within"? “内”是什么意思? Do you mean that you want to test if there's any overlap between the ranges, or if the first range is fully contained within another? 您是否要测试范围之间是否存在重叠,或者第一个范围是否完全包含在另一个范围中?

You can use Time objects in ranges and exploit #cover? 您可以在范围内使用时间对象并利用#cover? to check for overlap 检查重叠

start_time = 5.hours.ago
end_time = 4.hours.ago

check_range_start = (4.5).hours.ago
check_range_end = (3.5).hours.ago
check_range = (check_range_start..check_range_end)

check_range.cover?(end_time)   # => true
check_range.cover?(start_time) # =>false

If both ends of the range is covered by your check range, then your range is fully covered. 如果范围的两端都包含在您的检查范围之内,那么您的范围将被完全覆盖。 If only one end is covered, then you have overlap. 如果只覆盖一端,则说明您有重叠。 If neither end is covered, then the ranges do not intersect. 如果两端都没有覆盖,则范围不相交。

Once you know if there's intersection, then you can trivially compute the distance from one end of the time range to one end of your check range; 一旦知道是否存在交叉点,就可以轻松计算出时间范围的一端到检查范围的一端的距离; if you want to know how much time between your check range start and your input start time, simply subtract start_time - check_range_start . 如果您想知道从检查范围开始到输入开始时间之间的时间,只需减去start_time - check_range_start

There are several ways to perform this in the database which are far more performant than loading a bunch of records into Rails. 在数据库中执行此操作的方法有多种,它们比将一堆记录加载到Rails中的性能要好得多。

While "pure ruby" solutions are a quick fix they will exhaust the available memory and crash your server given a non-trivial amount of records. 尽管“纯红宝石”解决方案是一种快速解决方案,但在记录量不大的情况下,它们将耗尽可用内存并使服务器崩溃。

You can use a range together with .where to create a WHERE start_time BETWEEN a AND b clause that ensures that a time is within A and B. 您可以将范围与.where一起使用,以创建WHERE start_time BETWEEN a AND b子句,以确保时间在A和B之内。

starts_today = Model.where(
  start_time: Time.current.beginning_of_day..Time.current.end_of_day
)

If you want to ensure that the entire span between start_time and end_time is within a set of bounds you can write you own where clause: 如果要确保start_timeend_time之间的整个范围在一组范围内,则可以编写自己的where子句:

Model.where(
  "start_time > :a AND end_time < :b", 
  a: Time.current.beginning_of_day, 
  b: Time.current.end_of_day
)

I need to know how many of the hours is within the timerange. 我需要知道在该时间范围内有多少小时。

You can do this with the time/date functions in your database. 您可以使用数据库中的时间/日期函数来执行此操作。 On postgres for example you can do: 例如,在postgres上,您可以执行以下操作:

bounds = Time.current.beginning_of_day..Time.current.end_of_day
Model.select(
  "models.*,  (EXTRACT(HOUR FROM end_time - start_time ) - EXTRACT(HOUR FROM end_time - '#{ bounds.end.iso8601 }')) AS number_of_hours"
)

Again calculating this in the DB is vital if you for example want to use this in a WHERE clause. 如果例如您想在WHERE子句中使用它,则再次在数据库中计算该值至关重要。

I think I figured it out. 我想我知道了。 Shift.start_time.strftime("%H:%M") => '20:00' && Shift.end_time.strftime("%H:%M") <= '01:00' The .to_time was messing with me and also the ordering. Shift.start_time.strftime("%H:%M") => '20:00' && Shift.end_time.strftime("%H:%M") <= '01:00' 00'.to_time弄乱了我以及订购。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM