Ruby:计算2次之间的时差

时间:2022-06-23 16:24:15

I want to calculate the difference between 2 times. start_time: 22:00 (Rails interprets this as 2015-12-31 22:00:00 +0100) second_time: 02:00 (Rails interprets this as 2015-12-31 02:00:00 +0100). The second time is 4 hours later, so in the next day. Is there a way to calculate this difference?

我想计算2次之间的差异。 start_time:22:00(Rails将其解释为2015-12-31 22:00:00 +0100)second_time:02:00(Rails将此解释为2015-12-31 02:00:00 +0100)。第二次是4小时后,所以在第二天。有没有办法计算这种差异?

I can not simply do this: second_time - first_time, because this gives me a difference of 22 hours instead of 4 hours.

我不能简单地这样做:second_time - first_time,因为这给了我22小时而不是4小时的差异。

Edit: Some background information: A job is starting at 22:00 and ending the next day at 02:00. Because i fill in the form of this job only times, this times for the above 2 values are 2015-12-31 22:00:00 +0100 and 2015-12-31 02:00:00 +0100. I don't want the user to fill in the time including the date. The real difference between the times should be 4 hours.

编辑:一些背景信息:作业从22:00开始,到第二天02:00结束。因为我只填写这份工作的形式,所以上述2个值的时间是2015-12-31 22:00:00 +0100和2015-12-31 02:00:00 +0100。我不希望用户填写包括日期在内的时间。时间之间的真正差异应该是4个小时。

So what i actually want is calculate the difference between 22:00 and 02:00 (in the next day).

所以我真正想要的是计算22:00和02:00(第二天)之间的差异。

3 个解决方案

#1


8  

I don't understand why you think it should return 4 hours or why it does return 22 hours. 20 hours would be correct for your example:

我不明白为什么你认为它应该返回4小时或为什么它会返回22小时。你的例子20小时是正确的:

require 'time'

a = Time.parse('2015-12-31 22:00:00 +0100')
b = Time.parse('2015-12-31 02:00:00 +0100')

a - b
#=> 72000.0 # difference in seconds

(a - b) / 3600
#=> 20.0  # difference in hours

Update: It seems like you are dealing only with the time portion and not with the actual date. And I assume the maximum difference you will have to deal with is 24 hours:

更新:您似乎只处理时间部分而不是实际日期。我假设您必须处理的最大差异是24小时:

def time_difference(time_a, time_b)
  difference = time_b - time_a

  if difference > 0
    difference
  else
    24 * 3600 + difference 
  end
end

a = Time.parse('2015-12-31 22:00:00 +0100')
b = Time.parse('2015-12-31 02:00:00 +0100')
time_difference(a, b) / 3600
# => 4 # hours

a = Time.parse('2015-12-31 02:00:00 +0100')
b = Time.parse('2015-12-31 22:00:00 +0100')
time_difference(a, b) / 3600
# => 20 # hours

#2


1  

I'd write it thusly (before adding data checks), in an attempt to make it self-documenting:

我这样写(在添加数据检查之前),试图让它自我记录:

require 'time'

DT_FMT = '%Y-%m-%d %H:%M:%S %z'
SECONDS_PER_DAY = 24*60*60

def hours_elapsed(start_str, finish_str)
  start  = DateTime.strptime(start_str,  DT_FMT).to_time
  finish = DateTime.strptime(finish_str, DT_FMT).to_time
  finish = same_time_tomorrow(finish) if finish < start
  (finish-start)/3600
end

def same_time_tomorrow(time)
  time + SECONDS_PER_DAY
end

hours_elapsed '2015-12-31 22:00:00 +0100', '2015-12-31 02:00:00 +0100'
  #=>  4.0
hours_elapsed '2015-12-31 02:00:00 +0100', '2015-12-31 22:00:00 +0100'
  #=> 20.0

#3


0  

Old question but I did a nice method to deal with it:

老问题,但我做了一个很好的方法来处理它:

def time(start,ending)
  if start != ending
    medidas=["year","month","day","hour","minute","second"]
    array=[1970,1,1,0,0,0]
    text = ""
    Time.at(ending-start).utc.to_a.take(6).reverse.each_with_index do |k,i|
      text = "#{text} #{I18n.translate medidas[i].to_sym, count: k-array[i]}"
    end
    text = text.strip.squish
    pos = text.rindex(" ",(text.rindex(" ")-1))
    unless pos.nil?
      text = text.insert(pos," and")
    end
    text = text.strip.squish #This shouldn't be needed but just in case
  else
    "0 seconds"
  end
end

Then in config/locales/en.yml I added:

然后在config / locales / en.yml中我添加了:

en:
 año:
    zero: ''
    one: '1 year'
    other: '%{count} years'
 mes:
    zero: ''
    one: '1 month'
    other: '%{count} months'
 dia:
    zero: ''
    one: '1 day'
    other: '%{count} days'
 hora:
    zero: ''
    one: '1 hour'
    other: '%{count} hours'
 minuto:
    zero: ''
    one: '1 minute'
    other: '%{count} minutes'
 segundo:
    zero: ''
    one: '1 second'
    other: '%{count} seconds'

So for example when you call:

例如,当您致电时:

start = Time.now
ending = start + (60*60)

time(start,ending)
=> "1 hour"

ending = start + (60*60*28)
time(start,ending)
=> "1 day and 4 hours"

ending = start + (53*60*5874)
time(start,ending)
=> "7 months 4 days 4 hours and 42 minutes"

Hope it's useful

希望它有用

#1


8  

I don't understand why you think it should return 4 hours or why it does return 22 hours. 20 hours would be correct for your example:

我不明白为什么你认为它应该返回4小时或为什么它会返回22小时。你的例子20小时是正确的:

require 'time'

a = Time.parse('2015-12-31 22:00:00 +0100')
b = Time.parse('2015-12-31 02:00:00 +0100')

a - b
#=> 72000.0 # difference in seconds

(a - b) / 3600
#=> 20.0  # difference in hours

Update: It seems like you are dealing only with the time portion and not with the actual date. And I assume the maximum difference you will have to deal with is 24 hours:

更新:您似乎只处理时间部分而不是实际日期。我假设您必须处理的最大差异是24小时:

def time_difference(time_a, time_b)
  difference = time_b - time_a

  if difference > 0
    difference
  else
    24 * 3600 + difference 
  end
end

a = Time.parse('2015-12-31 22:00:00 +0100')
b = Time.parse('2015-12-31 02:00:00 +0100')
time_difference(a, b) / 3600
# => 4 # hours

a = Time.parse('2015-12-31 02:00:00 +0100')
b = Time.parse('2015-12-31 22:00:00 +0100')
time_difference(a, b) / 3600
# => 20 # hours

#2


1  

I'd write it thusly (before adding data checks), in an attempt to make it self-documenting:

我这样写(在添加数据检查之前),试图让它自我记录:

require 'time'

DT_FMT = '%Y-%m-%d %H:%M:%S %z'
SECONDS_PER_DAY = 24*60*60

def hours_elapsed(start_str, finish_str)
  start  = DateTime.strptime(start_str,  DT_FMT).to_time
  finish = DateTime.strptime(finish_str, DT_FMT).to_time
  finish = same_time_tomorrow(finish) if finish < start
  (finish-start)/3600
end

def same_time_tomorrow(time)
  time + SECONDS_PER_DAY
end

hours_elapsed '2015-12-31 22:00:00 +0100', '2015-12-31 02:00:00 +0100'
  #=>  4.0
hours_elapsed '2015-12-31 02:00:00 +0100', '2015-12-31 22:00:00 +0100'
  #=> 20.0

#3


0  

Old question but I did a nice method to deal with it:

老问题,但我做了一个很好的方法来处理它:

def time(start,ending)
  if start != ending
    medidas=["year","month","day","hour","minute","second"]
    array=[1970,1,1,0,0,0]
    text = ""
    Time.at(ending-start).utc.to_a.take(6).reverse.each_with_index do |k,i|
      text = "#{text} #{I18n.translate medidas[i].to_sym, count: k-array[i]}"
    end
    text = text.strip.squish
    pos = text.rindex(" ",(text.rindex(" ")-1))
    unless pos.nil?
      text = text.insert(pos," and")
    end
    text = text.strip.squish #This shouldn't be needed but just in case
  else
    "0 seconds"
  end
end

Then in config/locales/en.yml I added:

然后在config / locales / en.yml中我添加了:

en:
 año:
    zero: ''
    one: '1 year'
    other: '%{count} years'
 mes:
    zero: ''
    one: '1 month'
    other: '%{count} months'
 dia:
    zero: ''
    one: '1 day'
    other: '%{count} days'
 hora:
    zero: ''
    one: '1 hour'
    other: '%{count} hours'
 minuto:
    zero: ''
    one: '1 minute'
    other: '%{count} minutes'
 segundo:
    zero: ''
    one: '1 second'
    other: '%{count} seconds'

So for example when you call:

例如,当您致电时:

start = Time.now
ending = start + (60*60)

time(start,ending)
=> "1 hour"

ending = start + (60*60*28)
time(start,ending)
=> "1 day and 4 hours"

ending = start + (53*60*5874)
time(start,ending)
=> "7 months 4 days 4 hours and 42 minutes"

Hope it's useful

希望它有用