【问题标题】:Ruby: Calculate time difference between 2 timesRuby:计算2次之间的时间差
【发布时间】:2015-12-31 15:22:56
【问题描述】:

我想计算 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小时后,所以在第二天。有没有办法计算这种差异?

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

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

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

【问题讨论】:

  • 2015-12-31 02:00:00 +0100 怎么会在2015-12-31 22:00:00 +0100 之后的第二天呢?他们是同一天。

标签: ruby-on-rails ruby time


【解决方案1】:

我不明白您为什么认为它应该返回 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

更新:您似乎只处理时间部分而不是实际日期。我假设您必须处理的最大差异是 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

【讨论】:

  • 对不起,我在帖子中添加了一些背景信息,感谢您的回复。
  • @MattDice:我更新了我的答案。希望我正确理解了您的要求。
【解决方案2】:

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

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

然后在 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'

例如当你打电话时:

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"

希望有用

【讨论】:

    【解决方案3】:

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

    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
    

    hours_elapsed 的参数最好是只包含小时和分钟的字符串,在这种情况下我们也可以重命名该方法。 time_elapsed("18:00", "2:30") 是如何调用此方法的示例。

    MINUTES_PER_DAY = 24*60
    
    def time_elapsed(start_str, finish_str)
      start_mins = time_str_to_minutes(start_str)  
      finish_mins = time_str_to_minutes(finish_str)
      finish_mins += MINUTES_PER_DAY if
        finish_mins < start_mins
      (finish_mins-start_mins).divmod(60)
    end
    
    def time_str_to_minutes(str)
      hrs, mins = str.split(':').map(&:to_i)
      60 * hrs + mins
    end
    
    time_elapsed("8:00", "17:30")
      #=> [9, 30] 
    time_elapsed("18:00", "2:30")
      #=> [8, 30] 
    

    【讨论】:

    • 请帮助我了解如何使用您的解决方案,但只取 hour& min 而不是整个日期。因为当hours_elapsed '2015-12-31 22:00:00 +0100', '2015-12-31 02:00:00 +0100' 会给出4 hours_elapsed '2015-12-21 22:00:00 +0100', '2015-12-31 02:00:00 +0100' 会给出220.0 而我只需要小时和分钟。如果您愿意,我将不胜感激。
    • @Rubioli,请看我的编辑。我回答你的问题了吗?
    • 非常感谢@CarySwoveland。你是最棒的 :) 我有一个简单的问题,听起来可能很愚蠢。为什么将数组作为输出而不是像9:30? :)
    • 你可以这样做 ([9,30].join(':'))。是否应该取决于随后在程序中如何使用结果。如果需要单独的小时和分钟值,则返回一个数组会更有意义(而不是h,m = "9:30".split(":").map(&amp;:to_i))。
    • 有道理。非常感谢@CarySwoveland
    猜你喜欢
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 2012-09-18
    • 2015-03-14
    • 2018-04-03
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多