Formatting The Dates

The due date is now shown, but the formatting is ugly; we don’t really want the date and time in that format, or time zone displayed. This is happening because due_at is a Time object and the view code is calling to_s on it to display it. We do have some choice here, though. Rails extends the to_s method to give us options for controlling the display format. We’ll try some of them with our first task and see what formats they return.

Format

Result

Task.first.due_at.to_s

2009-02-19 00:00:00 UTC

Task.first.due_at.to_s(:long)

February 19, 2009 00:00

Task.first.due_at.to_s(:short)

19 Feb 00:00

Task.first.due_at.to_s(:db)

2009-02-19 00:00:00

There’s a good range there, but we’re being picky and we don’t want any of them. How could we
define our own custom format? Ruby’s Time object has a method called strftime that will
enable us to do just that. There are many control characters for the format string, though so we’ll look at the
Ruby documentation to see what’s available. We can do this by typing ri Time.strftime at the command
line, or by looking at the appropriate Ruby API documentation page. Either way will show us a list of format characters we can use.

Let’s try creating our own format string. We’ll update the relevant part of our view to show the due date in our own custom format.

ruby

<%= task.due_at.strftime("due on %B %d at %I:%M %p") %></li>

When we refresh our page we can see that the tasks’ due dates are now displayed as we want them.

The due dates now show in the correct format.

Tidying Up The Code

We’re now showing the dates in the format we want, but the view code is a little ugly and not easily reusable. We might want to use the same format in other places, so we’ll refactor a little to improve our code. There are a number of ways we could refactor the code: we could create a helper method or we could add a new method to the Task model. The route we’re going to take though is to add a new format to the to_s method. Instead of using :long, :short or :db we can create our own format and give it a name.

We’ll first change the code in our index view that displays the date in our new format.

ruby

<%= task.due_at.to_s(:due_date) %></li>

The date format needs to be loaded before the rest of the application so we’re going to add it to the environment.rb file. The various date formats are stored in a hash in the Date class called TIME_FORMATS, with the hash’s keys being strings representing the formats. All we need to do is add a new key called due_date to the hash with a value of our format string. At the bottom of environment.rb we’ll add the following line.

ruby

Time::DATE_FORMATS[:due_date] = "due on %B %d at %I:%M %p"

After we’ve added the new line and saved it we’ll have to restart our application so that the new format is picked up. If we don’t restart then the default to_s string will be displayed (and we’ll be back where we started!)

After we’ve restarted the application and gone back to the tasks index page we’ll see that our new date format is still showing and our code is much cleaner.