【问题标题】:how to convert 270921sec into days + hours + minutes + sec ? (ruby)如何将 270921sec 转换为天 + 小时 + 分钟 + 秒? (红宝石)
【发布时间】:2011-01-19 14:13:33
【问题描述】:

我有几秒钟的时间。假设是 270921。如何显示这个数字,表示它是 xx 天、yy 小时、zz 分钟、ww 秒?

【问题讨论】:

    标签: ruby time


    【解决方案1】:

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

    t = 270921
    mm, ss = t.divmod(60)            #=> [4515, 21]
    hh, mm = mm.divmod(60)           #=> [75, 15]
    dd, hh = hh.divmod(24)           #=> [3, 3]
    puts "%d days, %d hours, %d minutes and %d seconds" % [dd, hh, mm, ss]
    #=> 3 days, 3 hours, 15 minutes and 21 seconds
    

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

    【讨论】:

    • @Mike Woodhouse:这就是我想要的。谢谢。
    • +1,如果我需要显示直到 90 分钟的秒数,例如我正在跟踪游戏,该怎么办。它应该显示类似 90:54 的内容。谢谢!
    • @uDaY 查看我的增强答案。我不太明白你想做什么,但也许它会有所帮助。
    • 谢谢你,我要为它创建一个简洁的小方法:def seconds_to_dhms(seconds); [60,60,24].map{ |dm|秒,t = seconds.divmod(dm); t }.reverse.unshift 秒;结束
    • 使用此代码或 Benchmark 类进行基准测试是否更好(即仅计算完成某项工作所需的时间)?
    【解决方案2】:

    我希望有比使用 divmod 更简单的方法,但这是我发现的最干燥和可重复使用的方法:

    def seconds_to_units(seconds)
      '%d days, %d hours, %d minutes, %d seconds' %
        # the .reverse lets us put the larger units first for readability
        [24,60,60].reverse.inject([seconds]) {|result, unitsize|
          result[0,0] = result.shift.divmod(unitsize)
          result
        }
    end
    

    通过更改格式字符串和第一个内联数组(即[24,60,60])可以轻松调整该方法。

    增强版

    class TieredUnitFormatter
      # if you set this, '%d' must appear as many times as there are units
      attr_accessor :format_string
    
      def initialize(unit_names=%w(days hours minutes seconds), conversion_factors=[24, 60, 60])
        @unit_names = unit_names
        @factors = conversion_factors
    
        @format_string = unit_names.map {|name| "%d #{name}" }.join(', ')
        # the .reverse helps us iterate more effectively
        @reversed_factors = @factors.reverse
      end
    
      # e.g. seconds
      def format(smallest_unit_amount)
        parts = split(smallest_unit_amount)
        @format_string % parts
      end
    
      def split(smallest_unit_amount)
        # go from smallest to largest unit
        @reversed_factors.inject([smallest_unit_amount]) {|result, unitsize|
          # Remove the most significant item (left side), convert it, then
          # add the 2-element array to the left side of the result.
          result[0,0] = result.shift.divmod(unitsize)
          result
        }
      end
    end
    

    例子:

    fmt = TieredUnitFormatter.new
    fmt.format(270921)  # => "3 days, 3 hours, 15 minutes, 21 seconds"
    
    fmt = TieredUnitFormatter.new(%w(minutes seconds), [60])
    fmt.format(5454)  # => "90 minutes, 54 seconds"
    fmt.format_string = '%d:%d'
    fmt.format(5454)  # => "90:54"
    

    请注意,format_string 不会让您更改零件的顺序(它始终是最重要的值到最小的值)。对于更细粒度的控制,您可以使用split 并自己操作这些值。

    【讨论】:

      【解决方案3】:

      需要休息一下。打了这个:

      s = 270921
      dhms = [60,60,24].reduce([s]) { |m,o| m.unshift(m.shift.divmod(o)).flatten }
      # => [3, 3, 15, 21]
      

      【讨论】:

      【解决方案4】:

      Rails 有一个助手,可以将时间距离转换为文字。 你可以看看它的实现:distance_of_time_in_words

      【讨论】:

      • 有没有办法在 Rails 之外使用它?
      • 是的。包括 ActionView::Helpers::DateHelper !
      • a = distance_of_time_in_words(from_time, from_time + 50.minutes) => "约 1 小时" 1.9.2-p290 :035 >
      【解决方案5】:

      如果您使用的是 Rails,如果您不需要精度,有一个简单的方法:

      time_ago_in_words 270921.seconds.from_now
      # => 3 days
      

      【讨论】:

        【解决方案6】:

        你可以使用我找到的最简单的方法来解决这个问题:

          def formatted_duration total_seconds
            hours = total_seconds / (60 * 60)
            minutes = (total_seconds / 60) % 60
            seconds = total_seconds % 60
            "#{ hours } h #{ minutes } m #{ seconds } s"
          end
        

        您可以随时根据需要调整返回值。

        2.2.2 :062 > formatted_duration 3661
         => "1 h 1 m 1 s"
        

        【讨论】:

          【解决方案7】:

          我刚开始写红宝石。我想这仅适用于 1.9.3

          def dateBeautify(t)
          
              cute_date=Array.new
              tables=[ ["day", 24*60*60], ["hour", 60*60], ["minute", 60], ["sec", 1] ]
          
              tables.each do |unit, value|
                  o = t.divmod(value)
                  p_unit = o[0] > 1 ? unit.pluralize : unit
                  cute_date.push("#{o[0]} #{unit}") unless o[0] == 0
                  t = o[1]
              end
              return cute_date.join(', ')
          
          end
          

          【讨论】:

            【解决方案8】:

            我修改了@Mike给出的答案,根据结果的大小添加了动态格式

                  def formatted_duration(total_seconds)
                    dhms = [60, 60, 24].reduce([total_seconds]) { |m,o| m.unshift(m.shift.divmod(o)).flatten }
            
                    return "%d days %d hours %d minutes %d seconds" % dhms unless dhms[0].zero?
                    return "%d hours %d minutes %d seconds" % dhms[1..3] unless dhms[1].zero?
                    return "%d minutes %d seconds" % dhms[2..3] unless dhms[2].zero?
                    "%d seconds" % dhms[3]
                  end
            

            【讨论】:

              【解决方案9】:

              天数 = 270921/86400(一天中的秒数)= 3 天这是绝对数

              剩余秒数 (t) = 270921 - 3*86400 = 11721

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

              这会产生类似 3:03:15:21 的结果

              【讨论】:

                【解决方案10】:

                不是对 OP 的直接回答,但它可能会帮助到这里的人。

                我有这个字符串

                "Sorry, you cannot change team leader in the last #{freeze_period_time} of a #{competition.kind}"
                

                freeze_period_timeirb 中解析为 5 天,但在字符串中,它解析为以秒为单位的时间,例如 47200,所以字符串变得丑陋了

                "Sorry, you cannot change team leader in the last 47200 of a hackathon"
                

                要修复它,我必须在 freeze_period_time 对象上使用 .inspect

                所以下面的让它工作了

                "Sorry, you cannot change team leader in the last #{freeze_period_time.inspect} of a #{competition.kind}"
                

                返回正确的句子

                "Sorry, you cannot change team leader in the last 5 days of a hackathon"
                

                TLDR

                您可能需要time.inspect - https://www.geeksforgeeks.org/ruby-time-inspect-function/

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-01-06
                  • 2017-05-10
                  • 1970-01-01
                  • 2014-07-23
                  相关资源
                  最近更新 更多