Reputation: 779
Currently I'm using the following:
distance_of_time_in_words(tweet.created_at, Time.now + 30.minutes, include_seconds: false)
This works fine in most scenarios, but I'd like certain exceptions to be formatted differently, and the documentation is rather confusing for this scenario. (I also couldn't find any questions on here about it)
As an example, currently the function converts the time to this before 1 day has passed.
5 hours and 17 minutes ago
I'm using it for tweets posted and times such as
Tweeted 4 days, 8 hours, and 3 minutes
Seem a little long winded and unnecessarily specific.
Ideally I'd be like to be able to display:
less than a minute = the number of seconds ago
less than 1 hour = the amount of minutes
less than a day = the amount of hours
more than a day = the number of days
Is there a way of doing this?
Upvotes: 1
Views: 1273
Reputation: 46
The output of distance_of_time_in_words
(which is just an alias for time_ago_in_words
) should look like this:
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)
That looks like what you want. Something must be overriding distance_of_time_in_words
? I'm not sure why anything would do that, but that seems to be the case.
Upvotes: 1
Reputation: 110685
Here's a non-Rails solution, though it appears you are better off using Rails' distance_of_time_in_words
helper. Looking through the documentation, the latter seems to offer tremendous flexibility.
require 'time'
SECS_PER_MIN = 60
SECS_PER_HOUR = 60 * SECS_PER_MIN
SECS_PER_DAY = 24 * SECS_PER_HOUR
SECS_PER_WEEK = 7 * SECS_PER_DAY
SECS_PER_YEAR = 365 * SECS_PER_DAY
SECS_PER_CENT = 100 * SECS_PER_YEAR
SECS_PER_MLNM = 10 * SECS_PER_CENT
SECS_PER_EON = 1_000_000 * SECS_PER_MLNM
def message(secs)
case secs
when (0...SECS_PER_MIN)
"#{secs} seconds"
when (SECS_PER_MIN...SECS_PER_HOUR)
"#{secs/SECS_PER_MIN} minutes"
when (SECS_PER_HOUR...SECS_PER_DAY)
"#{secs/SECS_PER_HOUR} hours"
when (SECS_PER_DAY...SECS_PER_WEEK)
"#{secs/SECS_PER_DAY} days"
when (SECS_PER_WEEK...SECS_PER_YEAR)
"#{secs/SECS_PER_WEEK} weeks"
when (SECS_PER_YEAR...SECS_PER_CENT)
"#{secs/SECS_PER_YEAR} years"
when (SECS_PER_CENT...SECS_PER_MLNM)
"#{secs/SECS_PER_CENT} centuries"
when (SECS_PER_MLNM...SECS_PER_EON)
"#{secs/SECS_PER_MLNM} millenia"
else
"#{secs/SECS_PER_EON} eons"
end << " ago"
end
You would call message with something like:
message(Time.now-tweet_time)
Let's try it.
message(10) #=> "10 seconds ago"
message(1_000) #=> "16 minutes ago"
message(20_000) #=> "5 hours ago"
message(300_000) #=> "3 days ago"
message(10_000_000) #=> "16 weeks ago"
message(1_000_000_000) #=> "31 years ago"
message(25_000_000_000) #=> "7 centuries ago"
message(1_300_000_000_000) #=> "41 millenia ago"
message(100_000_000_000_000_000) #=> "3 eons ago"
You could prettify it by changing, for example,
when (SECS_PER_DAY...SECS_PER_WEEK)
"#{secs/SECS_PER_DAY} days"
to
when (SECS_PER_DAY...SECS_PER_WEEK)
n = secs/SECS_PER_DAY
n == 1 ? "1 day" : "#{n} days"
Upvotes: 1
Reputation: 106932
Perhaps you want to use the distance_of_time_in_words
helper:
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
and so on...
You can use that helper with just one argument. Something like this in your view should do the job:
Tweeted <%= time_ago_in_words(tweet.created_at) ago
Assuming tweet.created_at
is about 29 hours ago it would render to:
Tweeted 1 day ago
Upvotes: 1