instance method distance_of_time_in_words

Ruby on Rails edge

Available in: v2.2.3 v2.3.18 v3.0.20 v3.1.12 v3.2.22.5 v4.0.13 v4.1.16 v4.2.11.3 v5.0.7.2 v5.1.7 v5.2.8.1 v6.0.6.1 v6.1.7.10 v7.0.10 v7.1.6 v7.2.4 v8.0.5.1 v8.1.4 edge

Signature

distance_of_time_in_words(from_time, to_time = 0, options = {})

Reports the approximate distance in time between two Time, Date, or DateTime objects or integers as seconds. Pass include_seconds: true if you want more detailed approximations when distance < 1 min, 29 secs. Distances are reported based on the following table:

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
44 mins, 30 secs <-> 89 mins, 29 secs                                     # => about 1 hour
89 mins, 30 secs <-> 23 hrs, 59 mins, 29 secs                             # => about [2..24] hours
23 hrs, 59 mins, 30 secs <-> 41 hrs, 59 mins, 29 secs                     # => 1 day
41 hrs, 59 mins, 30 secs  <-> 29 days, 23 hrs, 59 mins, 29 secs           # => [2..29] days
29 days, 23 hrs, 59 mins, 30 secs <-> 44 days, 23 hrs, 59 mins, 29 secs   # => about 1 month
44 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs   # => about 2 months
59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 1 sec                    # => [2..12] months
1 yr <-> 1 yr, 3 months                                                   # => about 1 year
1 yr, 3 months <-> 1 yr, 9 months                                         # => over 1 year
1 yr, 9 months <-> 2 yr minus 1 sec                                       # => almost 2 years
2 yrs <-> max time or date                                                # => (same rules as 1 yr)

With include_seconds: true and the difference < 1 minute 29 seconds:

0-4   secs      # => less than 5 seconds
5-9   secs      # => less than 10 seconds
10-19 secs      # => less than 20 seconds
20-39 secs      # => half a minute
40-59 secs      # => less than a minute
60-89 secs      # => 1 minute

from_time = Time.now
distance_of_time_in_words(from_time, from_time + 50.minutes)                                # => about 1 hour
distance_of_time_in_words(from_time, 50.minutes.from_now)                                   # => about 1 hour
distance_of_time_in_words(from_time, from_time + 15.seconds)                                # => less than a minute
distance_of_time_in_words(from_time, from_time + 15.seconds, include_seconds: true)         # => less than 20 seconds
distance_of_time_in_words(from_time, 3.years.from_now)                                      # => about 3 years
distance_of_time_in_words(from_time, from_time + 60.hours)                                  # => 3 days
distance_of_time_in_words(from_time, from_time + 45.seconds, include_seconds: true)         # => less than a minute
distance_of_time_in_words(from_time, from_time - 45.seconds, include_seconds: true)         # => less than a minute
distance_of_time_in_words(from_time, 76.seconds.from_now)                                   # => 1 minute
distance_of_time_in_words(from_time, from_time + 1.year + 3.days)                           # => about 1 year
distance_of_time_in_words(from_time, from_time + 3.years + 6.months)                        # => over 3 years
distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => about 4 years

to_time = Time.now + 6.years + 19.days
distance_of_time_in_words(from_time, to_time, include_seconds: true)                        # => about 6 years
distance_of_time_in_words(to_time, from_time, include_seconds: true)                        # => about 6 years
distance_of_time_in_words(Time.now, Time.now)                                               # => less than a minute

With the scope option, you can define a custom scope for Rails to look up the translation.

For example you can define the following in your locale (e.g. en.yml).

datetime:
  distance_in_words:
    short:
      about_x_hours:
        one: 'an hour'
        other: '%{count} hours'

See github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml for more examples.

Which will then result in the following:

from_time = Time.now
distance_of_time_in_words(from_time, from_time + 50.minutes, scope: 'datetime.distance_in_words.short') # => "an hour"
distance_of_time_in_words(from_time, from_time + 3.hours, scope: 'datetime.distance_in_words.short')    # => "3 hours"

Parameters

from_time req
to_time opt = 0
options opt = {}
Source
# File actionview/lib/action_view/helpers/date_helper.rb, line 106
      def distance_of_time_in_words(from_time, to_time = 0, options = {})
        locale = options[:locale]
        scope  = options.fetch(:scope, :'datetime.distance_in_words')

        from_time = normalize_distance_of_time_argument_to_time(from_time)
        to_time = normalize_distance_of_time_argument_to_time(to_time)
        from_time, to_time = to_time, from_time if from_time > to_time
        distance_in_minutes = ((to_time - from_time) / 60.0).round
        distance_in_seconds = (to_time - from_time).round

        case distance_in_minutes
        when 0..1
          return distance_in_minutes == 0 ?
                 distance_translation(:less_than_x_minutes, 1, locale, scope) :
                 distance_translation(:x_minutes, distance_in_minutes, locale, scope) unless options[:include_seconds]

          case distance_in_seconds
          when 0..4   then distance_translation(:less_than_x_seconds, 5, locale, scope)
          when 5..9   then distance_translation(:less_than_x_seconds, 10, locale, scope)
          when 10..19 then distance_translation(:less_than_x_seconds, 20, locale, scope)
          when 20..39 then distance_translation(:half_a_minute, nil, locale, scope)
          when 40..59 then distance_translation(:less_than_x_minutes, 1, locale, scope)
          else             distance_translation(:x_minutes, 1, locale, scope)
          end

        when 2...45           then distance_translation(:x_minutes, distance_in_minutes, locale, scope)
        when 45...90          then distance_translation(:about_x_hours, 1, locale, scope)
          # 90 mins up to 24 hours
        when 90...1440        then distance_translation(:about_x_hours, (distance_in_minutes.to_f / 60.0).round, locale, scope)
          # 24 hours up to 42 hours
        when 1440...2520      then distance_translation(:x_days, 1, locale, scope)
          # 42 hours up to 30 days
        when 2520...43200     then distance_translation(:x_days, (distance_in_minutes.to_f / 1440.0).round, locale, scope)
          # 30 days up to 60 days
        when 43200...86400    then distance_translation(:about_x_months, (distance_in_minutes.to_f / 43200.0).round, locale, scope)
          # 60 days up to 365 days
        when 86400...525600   then distance_translation(:x_months, (distance_in_minutes.to_f / 43200.0).round, locale, scope)
        else
          from_year = from_time.year
          from_year += 1 if from_time.month >= 3
          to_year = to_time.year
          to_year -= 1 if to_time.month < 3

          leap_years = if from_year > to_year
            0
          else
            fyear = from_year - 1
            (to_year / 4 - to_year / 100 + to_year / 400) - (fyear / 4 - fyear / 100 + fyear / 400)
          end
          minute_offset_for_leap_year = leap_years * 1440

          # Discount the leap year days when calculating year distance.
          # e.g. if there are 20 leap year days between 2 dates having the same day
          # and month then based on 365 days calculation
          # the distance in years will come out to over 80 years when in written
          # English it would read better as about 80 years.
          minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
          remainder                   = (minutes_with_offset % MINUTES_IN_YEAR)
          distance_in_years           = (minutes_with_offset.div MINUTES_IN_YEAR)
          if remainder < MINUTES_IN_QUARTER_YEAR
            distance_translation(:about_x_years, distance_in_years, locale, scope)
          elsif remainder < MINUTES_IN_THREE_QUARTERS_YEAR
            distance_translation(:over_x_years, distance_in_years, locale, scope)
          else
            distance_translation(:almost_x_years, distance_in_years + 1, locale, scope)
          end
        end
      end

Defined in actionview/lib/action_view/helpers/date_helper.rb line 106 · View on GitHub · Improve this page · Find usages on GitHub

Defined in ActionView::Helpers::DateHelper

Type at least 2 characters to search.

Use the arrow keys to navigate results, Enter to open one, Escape to close.

Keyboard shortcuts

/
Focus search
⌘K / Ctrl-K
Command palette
?
This help
Esc
Close