【问题标题】:How to dry `DD:HH:MM:SS` time format logic如何干燥`DD:HH:MM:SS`时间格式逻辑
【发布时间】:2016-03-31 03:04:10
【问题描述】:

我想得到:

  • 60s 格式当sec==60 (dd==0 && hh==0 && mm==0)
  • 1min 30s 格式当sec==90 (dd==0 && hh==0)

我这样做了:

def sec_int2str(sec)
  mm, ss = sec.divmod(60)
  hh, mm = mm.divmod(60)
  dd, hh = hh.divmod(24)
  if dd==0 && hh==0 && mm==0
    "#{ss}s"
  elsif dd==0 && hh==0
    "#{mm}min #{ss}s"
  elsif dd==0
    "#{hh}h #{mm}min #{ss}s"
  else
    "#{dd}d #{hh}h #{mm}min #{ss}s"
  end
end

但是逻辑太复杂了。我怎样才能简单地转换?

【问题讨论】:

  • 什么是ssSmmM
  • 你确定这不是python?
  • @AndyGauge 这是在 ruby​​ 中格式化字符串的另一种方法,试试这个
  • @sawa 输出类似60s 1min 30s

标签: ruby-on-rails ruby date time


【解决方案1】:

基于how to convert 270921sec into days + hours + minutes + sec ? (ruby),您获取传入秒数并获得hh mmss

那么你可以:

[
  hh>0 && "#{hh} hours",
  mm>0 && "#{mm} minutes",
  ss>0 && "#{ss} seconds",
].join ', '

当然,如果分钟为零,您可以从中得到“2 小时 4 秒”。

【讨论】:

    【解决方案2】:

    正如您已经确定的那样,您基本上一遍又一遍地执行相同的操作 (Numeric#divmod),但间隔不同(60、60、24)。那么,对我来说,一个简单的解决方案是将这些间隔与相应的标签一起放入数据结构中:

    UNITS = {
      "s"   => 60,
      "min" => 60,
      "h"   => 24,
      "d"   => Float::INFINITY
    }.freeze
    

    注意我们的“顶部”间隔使用Float::INFINITY。现在我们可以使用Enumerable#reduce 来迭代区间和标签,在每次迭代中将前一个divmod 商除以新区间:

    def sec_int2str(quo)
      UNITS.reduce([]) do |memo, (unit, int)|
        break memo if quo == 0
        break memo.unshift("#{quo}#{unit}") if quo == int
        quo, rem = quo.divmod(int)
        memo.unshift("#{rem.to_i}#{unit}")
      end.join(' ')
    end
    

    如您所见,如果商为 0,则第一个 break 会提前结束迭代,因此我们不会得到 0d 0h ...。如果商等于当前区间,则第二个break 结束迭代,因此我们得到60s 而不是1h 0s(和24h ... 而不是1d 0h ...)。

    让我们测试一下:

    secs = 1
    mins = 60 * secs
    hrs  = 60 * mins
    days = 24 * hrs
    
    [ 60 * secs,
      90 * secs,
      60 * mins,
      90 * mins + 15 * secs,
       6 * hrs  + 55 * mins + 30 * secs,
       1 * days + 10 * secs,
      75 * hrs  + 30 * mins
    ].each do |num|
      printf("%6d => %s\n", num, sec_int2str(num))
    end
    

    输出:

        60 => 60s
        90 => 1min 30s
      3600 => 60min 0s
      5415 => 1h 30min 15s
     24930 => 6h 55min 30s
     86410 => 24h 0min 10s
    271800 => 3d 3h 30min 0s
    

    看起来不错!

    【讨论】:

    • 这真是神奇的工作!所以看来学好数学是很重要的。
    • 这里唯一不在你自己代码中的数学是Float::INFINITY,这只是从n.divmod(x)中得到n的一个技巧(因为当你整数除以无穷大时,余数是总是分子)。或者,我们可以使用nil,然后在每次迭代中进行明确的int.nil? 检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-04
    相关资源
    最近更新 更多