【问题标题】:How do I get the number of seconds between two DateTimes in Ruby on Rails如何在 Ruby on Rails 中获取两个 DateTimes 之间的秒数
【发布时间】:2009-02-19 22:57:42
【问题描述】:

我有代码可以为员工进行时间跟踪。它会创建一个计数器来向员工显示他们打卡的时间。

这是当前代码:

  start_time = Time.parse(self.settings.first_clock_in)
  total_seconds = Time.now - start_time
  hours = (total_seconds/ 3600).to_i
  minutes = ((total_seconds % 3600) / 60).to_i
  seconds = ((total_seconds % 3600) % 60).to_i

这很好用。但是因为时间限制在 1970 - 2038 的范围内,我们试图用 DateTimes 替换所有时间使用。我不知道如何获得两个日期时间之间的秒数。减去它们会产生我不知道如何解释的 Rational,而减去 Times 会产生以秒为单位的差异。

注意:从 Ruby 1.9.2 开始,时间的硬性限制被移除。但是,时间针对 1823-11-12 和 2116-02-20 之间的值进行了优化。

【问题讨论】:

    标签: ruby-on-rails datetime


    【解决方案1】:

    减去两个 DateTimes 会返回以天为单位的经过时间,所以你可以这样做:

    elapsed_seconds = ((end_time - start_time) * 24 * 60 * 60).to_i
    

    【讨论】:

    • 啊,我知道它会在几天内返回它,我不知道这也包括一天的一小部分。谢谢。
    • 这在闰秒 (en.wikipedia.org/wiki/Leap_second) 的情况下无法正常工作。
    • 只是给可能对此感到困惑的任何人的说明。是的,减去两个DateTimes 返回经过的时间(以天为单位)。但是,在 Rails 中,您迁移为 datetime 的模型属性实际上可能是 ActiveSupport::TimeWithZone,并减去其中两个返回经过的时间,以 为单位。
    • 我正在使用它并得到一个分数,日期时间相隔 2 秒,15 和 13,但我得到的是 1.939 秒而不是 2 秒,并且 .to_i 被截断为 1 秒。跨度>
    【解决方案2】:

    或者,更易读:

    diff = datetime_1 - datetime_2
    diff * 1.days # => difference in seconds; requires Ruby on Rails
    

    请注意,您或其他搜索者可能真正在寻找的是:

    diff = datetime_1 - datetime_2
    Date.day_fraction_to_time(diff) # => [h, m, s, frac_s]
    

    【讨论】:

    • 这似乎不适用于(created_at 和 updated_at)。我的两个号码是2016-08-07 20:33:54.8635682016-08-07 20:33:54.788684,但区别是6469.9776。 Posgres 说这些字段是“没有时区的时间戳”,如果这有区别的话。
    • NoMethodError: undefined method `days' for 1:Fixnum
    • 请注意,.days 是一种 rails 方法,没有它在 ruby​​ 中不可用。
    • 这也应该有帮助 => diff.days.seconds
    【解决方案3】:

    您可以使用to_f 将它们转换为浮点数,但这会导致通常与浮点数相关的精度损失。如果您只是在整秒内转换为整数,它不应该大到令人担心。

    结果以秒为单位:

    >> end_time.to_f - start_time.to_f
    => 7.39954495429993
    
    >> (end_time.to_f - start_time.to_f).to_i
    => 7
    

    否则,您可以查看在 DateTime 对象上使用 to_formatted_s 并查看是否可以将输出哄骗为 Decimal 类将接受的内容,或者将其格式化为纯 Unix 时间作为字符串并调用 @987654325 @关于那个。

    【讨论】:

    • 感谢 Luke,.to_f 转换很棒!它独立于 Date 类工作:它是 DateTime 或 ActiveSupport::TimeWithZone。
    • NoMethodError: #<0x00000002240840>
    【解决方案4】:

    其他人错误地依赖分数或辅助函数。它比这简单得多。 DateTime 本身是下面的整数。这是 Ruby 的方式:

    stop.to_i - start.to_i
    

    例子:

    start = Time.now
     => 2016-06-21 14:55:36 -0700
    stop = start + 5.seconds
     => 2016-06-21 14:55:41 -0700
    stop.to_i - start.to_i
     => 5
    

    【讨论】:

    • 这仅适用于Time 而不是DateTime: NoMethodError (undefined method to_i for #&lt;DateTime:xxx&gt;)
    【解决方案5】:

    我正在使用 ruby​​-2.1.4,对我来说以下工作

    Time.now - Time.new(2014,11,05,17,30,0)
    

    给了我

    的时差

    参考:ruby doc

    【讨论】:

    • OP 指的是“DateTime”对象而不是“时间”对象。
    【解决方案6】:

    有一种方法可以做到这一点:

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

    等于 10。

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

    希望我能帮上忙。

    【讨论】:

    • 我们说的是 DateTime 类而不是 Time 类。
    【解决方案7】:

    像这样定义一个 Ruby 函数,

    def time_diff(start_time, end_time)
      seconds_diff = (start_time - end_time).to_i.abs
    
      days = seconds_diff / 86400 
      seconds_diff -= days * 86400
    
      hours = seconds_diff / 3600  
      seconds_diff -= hours * 3600
    
      minutes = seconds_diff / 60
      seconds_diff -= minutes * 60
    
      seconds = seconds_diff
    
      "#{days} Days #{hours} Hrs #{minutes} Min #{seconds} Sec"
     end
    

    并调用这个函数,

    time_diff(Time.now, Time.now-4.days-2.hours-1.minutes-53.seconds)
    

    【讨论】:

      【解决方案8】:

      为什么不使用内置的 "sec" 。这是一个例子:

      t1 = Time.now.sec 
      
      elapsed_t = Time.now.sec - t1
      
      puts "it took me :  #{elapsed_t} seconds to do something that is useful \n"
      

      【讨论】:

      • sec 方法将返回每个时间的秒部分,不包括分钟、小时等...而是可以使用例如to_i 使用自 epoc 以来的总秒数。
      • .sec 显示的是当前时间的秒数,不是正确的选项
      猜你喜欢
      • 2021-09-16
      • 1970-01-01
      • 2012-03-14
      • 2015-12-24
      • 2019-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多