【问题标题】:Rails - Get the time difference in hours, minutes and secondsRails - 以小时、分钟和秒为单位获取时差
【发布时间】:2013-11-04 22:13:12
【问题描述】:

我正在寻找一种惯用的方法来获取自给定日期以来经过的时间(以小时、分钟和秒为单位)。

如果给定日期是 2013-10-25 23:55:00,当前日期是 2013-10-27 20:55:09,则返回值应该是 45:03:09。 time_differencetime_diff gem 不能满足这个要求。

【问题讨论】:

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


【解决方案1】:
time_diff = Time.now - 2.minutes.ago
Time.at(time_diff.to_i.abs).utc.strftime "%H:%M:%S"
=> "00:01:59"

或者,如果您的应用对舍入很挑剔,只需将 to_i 替换为 round:

  Time.at(time_diff.round.abs).utc.strftime "%H:%M:%S"
   => => "00:02:00"

虽然不确定是惯用的部分

更新:如果预计时差超过 24 小时,则上述代码不正确。如果是这种情况,可以按照@MrYoshiji 的回答或调整上述解决方案以手动从日期时间对象计算小时数:

def test_time time_diff
  time_diff = time_diff.round.abs
  hours = time_diff / 3600

  dt = DateTime.strptime(time_diff.to_s, '%s').utc
  "#{hours}:#{dt.strftime "%M:%S"}"
end

test_time Time.now - 28.hours.ago - 2.minutes - 12.seconds
=> "27:57:48" 
test_time Time.now - 8.hours.ago - 2.minutes - 12.seconds
=> "7:57:48" 
test_time Time.now - 24.hours.ago - 2.minutes - 12.seconds
=> "23:57:48" 
test_time Time.now - 25.hours.ago - 2.minutes - 12.seconds
=> "24:57:48" 

【讨论】:

  • 不适用于time_diff = Time.now - 2.days.ago,返回 23:59:59
  • 由于四舍五入,损失了 1 秒。如果它与您的应用程序逻辑相关,您可以将 to_i 调用更改为 round
  • 这很干净,但它不会在 24 小时后返回任何东西。
  • 该死!更新了答案:/
  • @MrYoshiji - 他的回答现在正确吗?是否有任何测试用例可以验证他的最新代码?
【解决方案2】:

你可以试试这个:

def time_diff(start_time, end_time)
  seconds_diff = (start_time - end_time).to_i.abs

  hours = seconds_diff / 3600
  seconds_diff -= hours * 3600

  minutes = seconds_diff / 60
  seconds_diff -= minutes * 60

  seconds = seconds_diff

  "#{hours.to_s.rjust(2, '0')}:#{minutes.to_s.rjust(2, '0')}:#{seconds.to_s.rjust(2, '0')}"
  # or, as hagello suggested in the comments:
  # '%02d:%02d:%02d' % [hours, minutes, seconds]
end

并使用它:

time_diff(Time.now, Time.now-2.days-3.hours-4.minutes-5.seconds)
# => "51:04:04"

【讨论】:

  • 使用此代码或 Benchmark 类进行基准测试是否更好(即仅计算完成某项工作所需的时间)?
  • 您应该为此使用内置基准或 gem。 “不要重新发明轮子”;-)
  • “to_i”不是将减法得到的理性值四舍五入吗?每当我使用它时,即使花费了几分钟,我最终也会得到“0”。看来您需要使用to_f,对吧?
  • '%02d:%02d:%02d' % [hours, minutes, seconds]替换"#{hours.to_s.rjust(2, '0')}:#{minutes.to_s.rjust(2, '0')}:#{seconds.to_s.rjust(2, '0')}"怎么样?
  • @hagello 因为我没想到!感谢您的建议,我会将其添加到答案中并给您积分
【解决方案3】:

有一个方法:

Time.now.minus_with_coercion(10.seconds.ago)

等于 10(实际上是 9.99...,如果您想要 10,请使用 .round)。

来源:http://apidock.com/rails/Time/minus_with_coercion

希望我能帮上忙。

【讨论】:

    【解决方案4】:

    一旦你得到以秒为单位的时差,你可以做这样的事情

    Time.at(t).utc.strftime("%H:%M:%S")
    

    t 是以秒为单位的时差

    【讨论】:

    • 不幸的是,如果您的差异大于 1 天,这将不起作用...
    【解决方案5】:

    因为这没有被标记为重复,the response in the main thread 只是更清晰的恕我直言。我将在此处添加它以获得更多可见性:

    使用divmod 可以非常简洁地完成:

    t = (end_time - start_time).round.abs
    mm, ss = t.divmod(60)
    hh, mm = mm.divmod(60)
    puts "%02d:%02d:%02d" % [hh, mm, ss]
    

    您可以通过collectinject 发挥创意来进一步干燥它,但是当核心逻辑是三行时,它可能是矫枉过正。

    请注意,我已经更改了一些答案以更好地适应该线程的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-24
      • 1970-01-01
      • 2014-10-04
      • 2021-10-05
      • 2018-10-10
      • 1970-01-01
      • 2011-09-12
      相关资源
      最近更新 更多