Time Format
In the posts index page, if you take a look at the data displayed in created_at
column, you will see that the dates are formatted like this: 2023-03-25 13:24:12 +0800
. The format is too long and it includes the time zone which is redundant in most cases. It also follows a pattern that may not meet the specifications that you want.
Ruby has built in methods that will help you handle this problem, these methods allows you to convert the time into a string that follows a specific pattern.
Table of Contents
Formatting Time Using strftime
strftime
formats date according to the directives in the given format string. The directives begin with a percent (%) character. Any text not listed as a directive will be passed through to the output string.
Let’s try to use this to format the created_at
in the posts index page.
<!-- app/views/posts/index.html.erb -->
<!-- ... -->
<table>
<!-- ... -->
</thead>
<% @posts.each do |post| %>
<tr>
<!-- ... -->
- <td><%= post.created_at %></td>
+ <td><%= post.created_at.strftime("%Y/%m/%d %I:%M %p") %></td>
<!-- ... -->
</tr>
<% end %>
</table>
<!-- ... -->
The time format of created_at
changed from the default "%Y-%m-%d %H:%M:%S %z"
to "%Y/%m/%d %I:%M %p"
. The seconds and the time zone are removed, and it is converted to 12-hour clock format.
Below are the most commonly used directive, refer to Ruby Date Format (strftime) Cheat Sheet for the full list:
Date formatting
%Y | Year with century (e.g. 2015, 1995, etc) |
%m | Month of the year, zero-padded (01..12) |
%B | The full month name (e.g. January) |
%b | The abbreviated month name (e.g. Jan) |
%d | Day of the month, zero-padded (01..31) |
%j | Day of the year (001..366) |
Time Formatting
%H | Hour of the day, 24-hour clock, zero-padded (00..23) |
%k | Hour of the day, 24-hour clock, blank-padded (_0..23) |
%I | Hour of the day, 12-hour clock, zero-padded (01..12) |
%l | Hour of the day, 12-hour clock, blank-padded (_1..12) |
%P | Meridian indicator, lowercase (am or pm) |
%p | Meridian indicator, uppercase (AM or PM) |
%M | Minute of the hour (00..59) |
%S | Second of the minute (00..59) |
Weekday Formatting
%A | The full weekday name (e.g. Sunday) |
%^A | The full weekday name uppercased (e.g. SUNDAY) |
%a | The abbreviated weekday name (e.g. Sun) |
%^a | The abbreviated weekday name uppercased (e.g. SUN) |
%u | Day of the week starting Monday (1..7) |
%w | Day of the week starting Sunday (0..6) |
Formatting Time Using to_fs
You may also use Ruby’s pre-existing time formats using to_fs
or its alias to_formatted_s
. to_fs
converts time into a formatted string based on a predefined list of formats.
The code below shows the available time formats:
datetime = Time.now
datetime.to_fs(:db) # => "2007-12-04 00:00:00"
datetime.to_fs(:number) # => "20071204000000"
datetime.to_fs(:short) # => "04 Dec 00:00"
datetime.to_fs(:time) # => "06:16"
datetime.to_fs(:long) # => "December 04, 2007 00:00"
datetime.to_fs(:long_ordinal) # => "December 4th, 2007 00:00"
datetime.to_fs(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
datetime.to_fs(:iso8601) # => "2007-12-04T00:00:00+00:00"
datetime.to_fs(:nsec) # => "20071204061645953133115"
datetime.to_fs(:usec) # => "20071204061645953133"
The available predefined formats are limited. Luckily, you can add more time formats by adding new key-value pairs in Time::DATE_FORMATS
hash.
#config/application.rb
#...
module App
class Application < Rails::Application
#...
+ Time::DATE_FORMATS.merge!(default: '%Y/%m/%d %I:%M %p', ymd: '%Y/%m/%d')
end
end
#...
Restart your rails application and you can then use the formats you created.
datetime = Time.now
datetime.to_fs # => "2007-12-04 00:00 AM" ->default
datetime.to_fs(:ymd) # => "2007/12/04"
As you can see, without a parameter, to_fs
will return the :default
format.
You can now use this in your post index to change the time format of created_at
instead of using strftime
.
<!-- app/views/posts/index.html.erb -->
<!-- ... -->
<table>
<!-- ... -->
<% @posts.each do |post| %>
<tr>
<!-- ... -->
- <td><%= post.created_at.strftime("%Y/%m/%d %I:%M %p") %></td>
+ <td><%= post.created_at.to_fs %></td>
<!-- ... -->
</tr>
<% end %>
</table>
<!-- ... -->