【问题标题】:Ruby/Rails - How to convert seconds to time?Ruby/Rails - 如何将秒转换为时间?
【发布时间】:2011-04-27 05:00:51
【问题描述】:

我需要执行以下转换:

0     -> 12.00AM
1800  -> 12.30AM
3600  -> 01.00AM
...
82800 -> 11.00PM
84600 -> 11.30PM

我想出了这个:

(0..84600).step(1800){|n| puts "#{n.to_s} #{Time.at(n).strftime("%I:%M%p")}"}

这给了我错误的时间,因为 Time.at(n) 期望 n 是从纪元开始的秒数:

0     -> 07:00PM
1800  -> 07:30PM
3600  -> 08:00PM
...
82800 -> 06:00PM
84600 -> 06:30PM

对于这种转换,什么是最佳的、独立于时区的解决方案?

【问题讨论】:

    标签: ruby-on-rails ruby time timestamp seconds


    【解决方案1】:

    最简单的单行只是忽略日期:

    Time.at(82800).utc.strftime("%I:%M%p")
    
    #-> "11:00PM"
    

    【讨论】:

    • 注意:如果有人来这里寻找答案以获取将任意秒数(甚至是跨越数天的高计数)转换为不断增加的 HH:MM:SS 计数器(不仅限于到 24 小时跨度),那么这个答案不是解决方案。忽略日期,就像这个答案所建议的那样,每当跨越日期边界时,HH 计数器都会重置为 00。
    • @Magne 你的笔记是写给我的。现在,您对不断增加的 HH:MM:SS 的解决方案有什么建议吗?
    • @JoshuaPinter 是的,我找到了我的解决方案并将其作为答案发布在这里:stackoverflow.com/a/65166238/380607
    【解决方案2】:

    两个优惠:

    精心的 DIY 解决方案:

    def toClock(secs)
      h = secs / 3600;  # hours
      m = secs % 3600 / 60; # minutes
      if h < 12 # before noon
        ampm = "AM"
        if h = 0
          h = 12
        end
      else     # (after) noon
        ampm =  "PM"
        if h > 12
          h -= 12
        end
      end
      ampm = h <= 12 ? "AM" : "PM";
      return "#{h}:#{m}#{ampm}"
    end
    

    时间解决方案:

    def toClock(secs)
      t = Time.gm(2000,1,1) + secs   # date doesn't matter but has to be valid
      return "#{t.strftime("%I:%M%p")}   # copy of your desired format
    end
    

    HTH

    【讨论】:

      【解决方案3】:

      不确定这是否比

      (Time.local(1,1,1) + 82800).strftime("%I:%M%p")
      
      
      def hour_minutes(seconds)
        Time.at(seconds).utc.strftime("%I:%M%p")
      end
      
      
      irb(main):022:0> [0, 1800, 3600, 82800, 84600].each { |s| puts "#{s} -> #{hour_minutes(s)}"}
      0 -> 12:00AM
      1800 -> 12:30AM
      3600 -> 01:00AM
      82800 -> 11:00PM
      84600 -> 11:30PM
      

      斯蒂芬

      【讨论】:

      • 它又好又短,但我认为“toClock”的计算更直接,看起来更可靠。除了“toClock”应该拒绝负输入,并对输入执行“% 86400”。
      【解决方案4】:

      在其他解决方案中,小时计数器将在跨越 24 小时日边界时重置为 00。还要注意Time.at 向下舍入,因此如果输入有任何小数秒,它将给出错误的结果(例如,当t=479.9 然后Time.at(t).utc.strftime("%H:%M:%S") 将给出00:07:59 而不是00:08:00`是正确的)。

      如果您想要一种方法将任意秒数(即使是大于 24 小时跨度的高计数)转换为不断增加的 HH:MM:SS 计数器,并处理潜在的小数秒,请尝试以下操作:

      # Will take as input a time in seconds (which is typically a result after subtracting two Time objects),
      # and return the result in HH:MM:SS, even if it exceeds a 24 hour period.
      def formatted_duration(total_seconds)
        total_seconds = total_seconds.round # to avoid fractional seconds potentially compounding and messing up seconds, minutes and hours
        hours = total_seconds / (60*60)
        minutes = (total_seconds / 60) % 60 # the modulo operator (%) gives the remainder when leftside is divided by rightside. Ex: 121 % 60 = 1
        seconds = total_seconds % 60
        [hours, minutes, seconds].map do |t|
          # Right justify and pad with 0 until length is 2. 
          # So if the duration of any of the time components is 0, then it will display as 00
          t.round.to_s.rjust(2,'0')
        end.join(':')
      end
      

      根据@springerigor 的修改和https://gist.github.com/shunchu/3175001讨论中的建议

      【讨论】:

      • 干得好!我最终推出了使用ActiveSupport::Duration.build( seconds ).parts 的我自己的,但我非常喜欢你的,因为它更简单并且不需要我正在报废并用你的Rails 替换它的Rails。感谢发帖!
      • 我也交叉发布到这个要点,这似乎得到了很大的吸引力:gist.github.com/shunchu/3175001#gistcomment-3552126
      • 哎呀,我的错。没想到是同一个主旨。我已经继续并删除了我对该要点的评论。再次感谢。
      猜你喜欢
      • 2011-04-18
      • 2011-06-05
      • 2018-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 2011-08-28
      相关资源
      最近更新 更多