在Rails 3或Ruby中将持续时间转换为小时:分钟:秒(或类似)

cyd*_*nia 107 ruby datetime ruby-on-rails ruby-on-rails-3

我觉得有一种简单/内置的方法可以做到这一点,但我找不到它.

我有一个整数的持续时间(以秒为单位),我想以友好的格式显示它.

例如3600将显示为"01:00:00"或"1小时"或其他东西.

我可以这样做,time_ago_in_words(Time.zone.now+3600)但感觉有点像黑客,没有理由加上/减去当前时间只是为了格式化这个值.有没有duration_in_words()

谢谢

Lev*_*sky 189

加起来:

假如说 total_seconds = 3600

选项1:

distance_of_time_in_words(total_seconds) #=> "about 1 hour"
Run Code Online (Sandbox Code Playgroud)

选项2:

Time.at(total_seconds).utc.strftime("%H:%M:%S") #=> "01:00:00"
Run Code Online (Sandbox Code Playgroud)

选项3:

seconds = total_seconds % 60
minutes = (total_seconds / 60) % 60
hours = total_seconds / (60 * 60)

format("%02d:%02d:%02d", hours, minutes, seconds) #=> "01:00:00"
Run Code Online (Sandbox Code Playgroud)

使用选项1,如果你想的话,1选项,如果你想H:M:S格式,选项3,如果你想H:M:S格式,可以有24小时以上

  • 请注意,strftime选项将在24小时后溢出.如果持续时间为25小时,则会显示"01:00:00". (10认同)
  • 这在负时间不起作用,例如-1800返回-1h 30m而不是-30m (2认同)

IAm*_*NaN 39

Ruby的字符串%运算符太过不受重视并且被遗忘了.

"%02d:%02d:%02d:%02d" % [t/86400, t/3600%24, t/60%60, t%60]
Run Code Online (Sandbox Code Playgroud)

给定t是以秒为单位的持续时间,这将发出零填充冒号分隔的字符串,包括天.例:

t = 123456
"%02d:%02d:%02d:%02d" % [t/86400, t/3600%24, t/60%60, t%60]
=> "01:10:17:36"
Run Code Online (Sandbox Code Playgroud)

可爱.

  • 这是"可爱"的奇怪定义. (19认同)
  • `%`说,"从右边拿出参数数组,然后将它们插入我左边的格式字符串中." 在这方面,它类似于C\C++中的`printf`,只是更简洁,可以在赋值中使用.是的,我称之为可爱.功能强大.有些例子可以更好地证明这种口才,但他们不会回答这个问题.你的斯纳克不受赏识,顺便说一下. (8认同)

Cri*_*dma 22

我想你也可以这样做:

(Time.mktime(0)+3600).strftime("%H:%M:%S")
Run Code Online (Sandbox Code Playgroud)

根据需要格式化.

BTW,最初我想过使用Time.at(),但似乎我的Ubuntu上的EPOCH时间是Thu Jan 01 01:00:00 +0100 1970而不是00:00:00小时,正如我所料,因此如果我这样做:

Time.at(3600).strftime("%H:%M:%S")
Run Code Online (Sandbox Code Playgroud)

给了我超过想要的1小时.

  • 唯一的问题是如果你处理的时间超过24小时.在这种情况下,小时数将回滚到较低的数字. (6认同)

She*_*yar 14

我使用它来显示我的Rails项目中的持续时间:

  1. Integer该类添加自定义方法.您可以pretty_duration.rbinitializers文件夹中创建一个新文件:

    class Integer
        def pretty_duration
            parse_string = 
                if self < 3600
                    '%M:%S'
                else
                    '%H:%M:%S'
                end
    
            Time.at(self).utc.strftime(parse_string)
        end
    end
    
    Run Code Online (Sandbox Code Playgroud)
  2. seconds.pretty_duration在项目的任何地方打电话:

    275.pretty_duration     # => "04:35"
    9823.pretty_duration    # => "02:43:43"
    
    Run Code Online (Sandbox Code Playgroud)

这个答案建立在Lev Lukomsky的准则之上


Sat*_*ish 12

ActiveSupport::Duration.build+inspect给你有效的结果

 >> ActiveSupport::Duration.build(125557).inspect
 => "1 day, 10 hours, 52 minutes, and 37 seconds"
Run Code Online (Sandbox Code Playgroud)


Bre*_*don 9

这个使用晦涩的divmod方法同时划分和模数,所以它Float正确地处理秒:

def duration(seconds)
  minutes, seconds = seconds.divmod(60)
  hours, minutes = minutes.divmod(60)
  days, hours = hours.divmod(24)

  "#{days.to_s.rjust(3)}d #{hours.to_s.rjust(2)}h #{minutes.to_s.rjust(2)}m #{seconds}s"
end
Run Code Online (Sandbox Code Playgroud)


Igo*_*ger 7

使用Time.utc.strftime仅适用于总小时数小于 24 的值

2.2.2 :004 > Time.at(60 * 60).utc.strftime('%H h %M m')
=> "01 h 00 m"
Run Code Online (Sandbox Code Playgroud)

对于更大的值,它返回不正确的结果:

2.2.2 :006 > Time.at(60 * 60 * 24).utc.strftime('%H h %M m')
 => "00 h 00 m"
Run Code Online (Sandbox Code Playgroud)

我建议使用我为这个问题找到的最简单的方法:

  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
Run Code Online (Sandbox Code Playgroud)

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


小智 6

超过一天的持续时间要小心。

(timing/3600).to_i.to_s.rjust(2,'0') + ":"+Time.at(timing).utc.strftime("%M:%S")
Run Code Online (Sandbox Code Playgroud)


Cyr*_*ris 5

灵感来自 Lev Lukomsky 的一个利用 ActiveSupport::Duration 和处理毫秒的答案(对基准代码有用)

# duration in ms modulus number of ms in one second
milliseconds = duration.in_milliseconds % 1.second.in_milliseconds

# duration in seconds modulus number of seconds in one minute
seconds = (duration / 1.second) % (1.minute / 1.second)

# duration in minutes modulus number of minutes in one hour
minutes = (duration / 1.minute) % (1.hour / 1.minute)

# duration in hours modulus number of hours in one day
hours = (duration / 1.hour) % (1.day / 1.hour)

format("%02d:%02d:%02d:%03d", hours, minutes, seconds, milliseconds) #=> "12:05:00:001"
Run Code Online (Sandbox Code Playgroud)

当然,您可以使用相关的 ActiveSupport 方法并重复相同的结构,以数天、数月、数年等时间轻松地扩展它。

请记住,对于过长的持续时间,这可能是不准确的,因为 1 个月的持续时间不是固定的天数,我不确定 AS:Duration 是如何处理的。


Jon*_*ern 5

向@joshuapinter致敬,他给出了最佳答案(以评论的形式)。

使用嵌入式替换dotiwgem 可以更好地控制输出的准确性,以满足不同的需求:

https://github.com/radar/distance_of_time_in_words

示例查看代码:

%label
  Logoff after:
  - expire_in = distance_of_time_in_words(Time.now, Time.now + user.custom_timeout.minutes, :only => [:minutes, :hours, :days])
  = expire_in
Run Code Online (Sandbox Code Playgroud)

结果是这样的:

Logoff after: 1 day, 13 hours, and 20 minutes
Run Code Online (Sandbox Code Playgroud)