Reputation:
I'm writing a Rails application, but can't seem to find how to do relative time, i.e. if given a certain Time class, it can calculate "30 seconds ago" or "2 days ago" or if it's longer than a month "9/1/2008", etc.
Upvotes: 225
Views: 133564
Reputation: 9362
Since the most answer here suggests time_ago_in_words.
Instead of using :
<%= time_ago_in_words(comment.created_at) %>
In Rails, prefer:
<abbr class="timeago" title="<%= comment.created_at.getutc.iso8601 %>">
<%= comment.created_at.to_s %>
</abbr>
along with a jQuery library http://timeago.yarp.com/, with code:
$("abbr.timeago").timeago();
Main advantage: caching
http://rails-bestpractices.com/posts/2012/02/10/not-use-time_ago_in_words/
Upvotes: 7
Reputation: 11882
If you're building a Rails application, you should use
Time.zone.now
Time.zone.today
Time.zone.yesterday
This gives you time or date in the timezone with which you've configured your Rails application.
For example, if you configure your application to use UTC, then Time.zone.now
will always be in UTC time (it won't be impacted by the change of British Summertime for example).
Calculating relative time is easy, eg
Time.zone.now - 10.minute
Time.zone.today.days_ago(5)
Upvotes: 2
Reputation: 7043
Another approach is to unload some logic from the backend and maek the browser do the job by using Javascript plugins such as:
jQuery time ago or its Rails Gem adaptation
Upvotes: 0
Reputation: 1967
Just to clarify Andrew Marshall's solution for using time_ago_in_words
(For Rails 3.0 and Rails 4.0)
If you are in a view
<%= time_ago_in_words(Date.today - 1) %>
If you are in a controller
include ActionView::Helpers::DateHelper
def index
@sexy_date = time_ago_in_words(Date.today - 1)
end
Controllers do not have the module ActionView::Helpers::DateHelper imported by default.
N.B. It is not "the rails way" to import helpers into your controllers. Helpers are for helping views. The time_ago_in_words method was decided to be a view entity in the MVC triad. (I don't agree but when in rome...)
Upvotes: 25
Reputation: 225
I've written a gem that does this for Rails ActiveRecord objects. The example uses created_at, but it will also work on updated_at or anything with the class ActiveSupport::TimeWithZone.
Just gem install and call the 'pretty' method on your TimeWithZone instance.
https://github.com/brettshollenberger/hublot
Upvotes: 1
Reputation: 7399
Take a look at the instance methods here:
This has useful methods such as yesterday, tomorrow, beginning_of_week, ago, etc.
Examples:
Time.now.yesterday
Time.now.ago(2.days).end_of_day
Time.now.next_month.beginning_of_month
Upvotes: 6
Reputation: 26384
Something like this would work.
def relative_time(start_time)
diff_seconds = Time.now - start_time
case diff_seconds
when 0 .. 59
puts "#{diff_seconds} seconds ago"
when 60 .. (3600-1)
puts "#{diff_seconds/60} minutes ago"
when 3600 .. (3600*24-1)
puts "#{diff_seconds/3600} hours ago"
when (3600*24) .. (3600*24*30)
puts "#{diff_seconds/(3600*24)} days ago"
else
puts start_time.strftime("%m/%d/%Y")
end
end
Upvotes: 10
Reputation: 16384
I've written this, but have to check the existing methods mentioned to see if they are better.
module PrettyDate
def to_pretty
a = (Time.now-self).to_i
case a
when 0 then 'just now'
when 1 then 'a second ago'
when 2..59 then a.to_s+' seconds ago'
when 60..119 then 'a minute ago' #120 = 2 minutes
when 120..3540 then (a/60).to_i.to_s+' minutes ago'
when 3541..7100 then 'an hour ago' # 3600 = 1 hour
when 7101..82800 then ((a+99)/3600).to_i.to_s+' hours ago'
when 82801..172000 then 'a day ago' # 86400 = 1 day
when 172001..518400 then ((a+800)/(60*60*24)).to_i.to_s+' days ago'
when 518400..1036800 then 'a week ago'
else ((a+180000)/(60*60*24*7)).to_i.to_s+' weeks ago'
end
end
end
Time.send :include, PrettyDate
Upvotes: 52
Reputation: 6418
Sounds like you're looking for the time_ago_in_words
method (or distance_of_time_in_words
), from ActiveSupport. Call it like this:
<%= time_ago_in_words(timestamp) %>
Upvotes: 377
Reputation: 4409
What about
30.seconds.ago
2.days.ago
Or something else you were shooting for?
Upvotes: 20
Reputation: 734
You can use the arithmetic operators to do relative time.
Time.now - 2.days
Will give you 2 days ago.
Upvotes: 12