How do you do relative time in Rails?

Ruby on-RailsRuby

Ruby on-Rails Problem Overview


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.

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

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) %>

Solution 2 - Ruby on-Rails

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

Solution 3 - Ruby on-Rails

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...)

Solution 4 - Ruby on-Rails

What about

30.seconds.ago
2.days.ago

Or something else you were shooting for?

Solution 5 - Ruby on-Rails

You can use the arithmetic operators to do relative time.

Time.now - 2.days 

Will give you 2 days ago.

Solution 6 - Ruby on-Rails

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

Solution 7 - Ruby on-Rails

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/

Solution 8 - Ruby on-Rails

Take a look at the instance methods here:

http://apidock.com/rails/Time

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

Solution 9 - Ruby on-Rails

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)

Solution 10 - Ruby on-Rails

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

Solution 11 - Ruby on-Rails

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionlol_wutView Question on Stackoverflow
Solution 1 - Ruby on-RailsBen ScofieldView Answer on Stackoverflow
Solution 2 - Ruby on-RailsMatthias WinkelmannView Answer on Stackoverflow
Solution 3 - Ruby on-RailsseoView Answer on Stackoverflow
Solution 4 - Ruby on-RailsHonzaView Answer on Stackoverflow
Solution 5 - Ruby on-RailsTonyLaView Answer on Stackoverflow
Solution 6 - Ruby on-RailsGordon WilsonView Answer on Stackoverflow
Solution 7 - Ruby on-RailsRahul gargView Answer on Stackoverflow
Solution 8 - Ruby on-RailsdavogonesView Answer on Stackoverflow
Solution 9 - Ruby on-RailsZack XuView Answer on Stackoverflow
Solution 10 - Ruby on-RailsBrett ShollenbergerView Answer on Stackoverflow
Solution 11 - Ruby on-RailsThe Whiz of OzView Answer on Stackoverflow