以人类可读的格式显示持续时间,例如" X小时,Y分钟和#34;

时间:2014-09-25 01:46:54

标签: ruby-on-rails ruby intervals

我正在使用Rails 4,Ruby 2.1和PostgreSQL。

我有一个名为“duration”的数据库字段,它是一种间隔数据类型。

当提取此列中的数据时,它以hh:mm:ss的格式返回,例如01:30:00。

我正在试图找出一种方法来显示: 1小时30分钟

其他例子: 02:00:00至2小时 02:15:00至2小时15分钟 02:01:00到2小时1分钟

任何建议表示赞赏。

6 个答案:

答案 0 :(得分:6)

我会从这样的事情开始:

def duration_of_interval_in_words(interval)
  hours, minutes, seconds = interval.split(':').map(&:to_i)

  [].tap do |parts|
    parts << "#{hours} hour".pluralize(hours)       unless hours.zero?
    parts << "#{minutes} minute".pluralize(minutes) unless minutes.zero?
    parts << "#{seconds} hour".pluralize(seconds)   unless seconds.zero?
  end.join(', ')
end

duration_of_interval_in_words('02:00:00')
# => '2 hours'

duration_of_interval_in_words('02:01:00')
# => '2 hours, 1 minute'

duration_of_interval_in_words('02:15:00')
# => '2 hours, 15 minutes'

答案 1 :(得分:0)

另见 ActionView :: Helpers :: DateHelper distance_of_time_in_words(及相关)

e.g。

0 <-> 29 secs # => less than a minute
30 secs <-> 1 min, 29 secs # => 1 minute
1 min, 30 secs <-> 44 mins, 29 secs # => [2..44] minutes
... etc

https://apidock.com/rails/ActionView/Helpers/DateHelper/distance_of_time_in_words

或许不适合包含在模型验证错误中? (这是我的用例)

答案 2 :(得分:0)

您可以尝试以下方法显示如下:

  • minutes_to_human(45)#45分钟
  • minutes_to_human(120)#2小时
  • minutes_to_human(75)#2.5小时
  • minutes_to_human(75)#1.15小时
def minutes_to_human(minutes)
  result = {}

  hours = minutes / 60
  result[:hours] = hours if hours.positive?
  result[:minutes] = ((minutes * 60) - (hours * 60 * 60)) / 60 if minutes % 60 != 0

  result[:minutes] /= 60.0 if result.key?(:hours) && result.key?(:minutes)

  return I18n.t('helper.minutes_to_human.hours_minutes', time: (result[:hours] + result[:minutes]).round(2)) if result.key?(:hours) && result.key?(:minutes)
  return I18n.t('helper.minutes_to_human.hours', count: result[:hours]) if result.key?(:hours)
  return I18n.t('helper.minutes_to_human.minutes', count: result[:minutes].round) if result.key?(:minutes)
  ''
end

文:

en:
  helper:
    minutes_to_human:
      minutes:
        zero: '%{count} minute'
        one: '%{count} minute'
        other: '%{count} minutes'
      hours:
        one: '%{count} hour'
        other: '%{count} hours'
      hours_minutes: '%{time} hours'

答案 3 :(得分:0)

只需使用duration + inspect

seconds = 86400 + 3600 + 15
ActiveSupport::Duration.build(seconds).inspect
=> "1 day, 1 hour, and 15.0 seconds"

或者可以稍微自定义

ActiveSupport::Duration.build(seconds).parts.map do |key, value|
  [value.to_i, key].join 
end.join(' ')
=> "1days 1hours 15seconds"

P.S。

您可以获得秒数

1.day.to_i
=> 86400

时间只能以ISO8601格式解析

ActiveSupport::Duration.parse("PT2H15M").inspect
=> "2 hours and 15 minutes"

答案 4 :(得分:0)

这对我有用:

irb(main):030:0> def humanized_duration(seconds)
irb(main):031:1>   ActiveSupport::Duration.build(seconds).parts.except(:seconds).reduce("") do |output, (key, val)|
irb(main):032:2*       output+= "#{val}#{key.to_s.first} "
irb(main):033:2>     end.strip
irb(main):034:1>   end
=> :humanized_duration
irb(main):035:0> humanized_duration(920)
=> "15m"
irb(main):036:0> humanized_duration(3920)
=> "1h 5m"
irb(main):037:0> humanized_duration(6920)
=> "1h 55m"
irb(main):038:0> humanized_duration(10800)
=> "3h"

您可以更改您希望结果字符串在reduce 中的格式。我喜欢小时和分钟的“h”和“m”。我从持续时间部分排除了秒数,因为这对我的使用并不重要。

答案 5 :(得分:-1)

我发现duration.inspect非常适合这个目的。

> 10.years.inspect
=> "10 years"