[Ruby on Rails (RoR)] #distance_of_time_in_words, #time_ago_in_words in ActionView::Helpers::DateHelper

ActionView::Helpers::DateHelper

The Date Helper primarily creates select/option tags for different kinds of dates and times or date and time elements. All of the select-type methods share a number of common options that are as follows:

First, include ActionView::Helpers::DateHelper module.

1
2.6.1 :007 > include ActionView::Helpers::DateHelper

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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:

1
2
3
4
5
6
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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).

1
2
3
4
5
6
7
8
# locale/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 - https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml for more examples.

Which will then result in the following:

1
2
3
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"

distance_of_time_in_words_to_now(from_time, options = {})

Alias for: #time_ago_in_words.

#time_ago_in_words(from_time, options = {})

1
2
3
4
5
6
7
8
9
10
11
12
13
Like distance_of_time_in_words, but where to_time is fixed to Time.now.

time_ago_in_words(3.minutes.from_now) # => 3 minutes
time_ago_in_words(3.minutes.ago) # => 3 minutes
time_ago_in_words(Time.now - 15.hours) # => about 15 hours
time_ago_in_words(Time.now) # => less than a minute
time_ago_in_words(Time.now, include_seconds: true) # => less than 5 seconds

from_time = Time.now - 3.days - 14.minutes - 25.seconds
time_ago_in_words(from_time) # => 3 days

from_time = (3.days + 14.minutes + 25.seconds).ago
time_ago_in_words(from_time) # => 3 days

Note that you cannot pass a Numeric value to #time_ago_in_words.

Also aliased as: #distance_of_time_in_words_to_now

References

[1] ActionView::Helpers::DateHelper - https://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html#method-i-time_ago_in_words