Raw dates and times in Ruby are not too user-friendly!
The default times and datetimes in rails are pretty unattractive and contain more information than we usually need to display.
For example:
@user.created_at # => Mon, 18 May 2009 19:51:51 +0100
A useful way around this is to use the strftime()
method to specify the format of the date or time.
So instead, we can use:
@user.created_at.strftime("%d %b %y") # => "18 May 09"
This way we only display the information we want to.
Specifying time with strftime()
throughout an entire app is not ideal though; apart from anything else it’s not DRY. Also, if your strftime formats are quite elaborate, the chances of you mistyping them and leaving inconsistencies throughout your app are pretty high.
Enter: to_formatted_s()
to_formatted_s()
is a method available to classes Date
, Time
and DateTime
which converts the time format to a more practical format.
@user.created_at.to_formatted_s(:time) # => "20:06"
The default format is :default but you can specify any of the other pre-set formats by simply passing the name of the format as a parameter.
Classes Time
and DateTime
share these formats:
DATE_FORMATS = {
:db => "%Y-%m-%d %H:%M:%S", # => "2009-05-18 20:03:48"
:number => "%Y%m%d%H%M%S", # => "20090518200545"
:time => "%H:%M", # => "20:06"
:short => "%d %b %H:%M", # => "18 May 20:06"
:long => "%B %d, %Y %H:%M", # => "May 18, 2009 20:07"
:long_ordinal => lambda { |time| time.strftime("%B #{time.day.ordinalize}, %Y %H:%M") }, # => "May 18th, 2009 20:07"
:rfc822 => "%a, %d %b %Y %H:%M:%S %z" # => "Mon, 18 May 2009 20:08:25 +0100"
}
and the Date
class has these formats:
DATE_FORMATS = {
:short => "%e %b", #=> "18 May"
:long => "%B %e, %Y", # => "May 18, 2009"
:db => "%Y-%m-%d", # => "2009-05-18"
:number => "%Y%m%d", #=> "20090518"
:long_ordinal => lambda { |d| d.strftime("%B #{d.day.ordinalize}, %Y") }, # => "May 18th, 2009"
:rfc822 => "%e %b %Y" # => "18 May 2009"
}
(RFC822 is the standard for the format of ARPA internet text messages.)
As well as using these default time formats, you can also set your own formats that can be used throughout your entire app.
To do this, simply expand on the default DATE_FORMATS
.
First, create a new file: config/initializers/datetime_formats.rb and add the following:
Date::DATE_FORMATS[:my_format] = lambda { |t| t.strftime("#{time.day.ordinalize} of %B, %Y") }
Time::DATE_FORMATS[:my_format] = lambda { |t| t.strftime("#{time.day.ordinalize} of %B, %Y") }
If you’re setting the same format(s) on both Date
and Time
then this can be further simplified to:
[Time, Date].map do |klass|
klass::DATE_FORMATS[:my_format] = lambda { |t| t.strftime("#{time.day.ordinalize} of %B, %Y") }
end
Now all you have to do is call
<%= @user.created_at.to_formatted_s(:my_format) %>
or even simpler:
<%= @user.created_at.to_s(:my_format) %>
Much DRYer! :)
Jo Hund has put together a great cheat-sheet for stfrtime formats, it’s available here as a .pdf download.