Formatting dates and times in Rails with I18n.localize

January 3, 2015

irb(main):001:0> Date.today.strftime("%d-%m-%y")
=> "03-01-15"

The typical way of formatting a date in Rails apps is to use the standard #strftime. This works great to start with, but repeating the formats again and again throughout your code leads to issues with maintainability. If you want to change the format you’ll need to go through many different files, and you’ll probably end up with inconsistent formats used throughout your application.

Rails of course comes with a way to avoid this though the use of the Rails internationalisation (I18n) API. The I18n module has a #localize method which you can pass a Date, DateTime or Time object to.

irb(main):002:0> I18n.localize Date.today
=> "2015-01-03"

By default that just does the same as calling .to_s on the object, but you can also pass a format name:

irb(main):003:0> I18n.localize Date.today, format: :short
=> "Jan 03"
irb(main):004:0> I18n.localize Date.today, format: :long
=> "January 03, 2015"

Under the hood it’s just I18n, so you can define your own date formats using the standard formats. If you have this in config/locales/en.yml:

en:
  dates:
    formats:
      date_month_year_concise: '%d-%m-%y'

Then you can use the custom format like this:

irb(main):005:0> I18n.localize Date.today, format: :date_month_year_concise
=> "03-01-15"

(I prefer to give the formats most descriptive names than ‘short’ or ‘long’ as it’s easier to refer back to which is which later)

This not only makes your code more maintainable and consistent, if you ever want to internationalise your app you don’t have to worry about dates. You’ve already done the hard work, so you just need to define the new locale specific format:

irb(main):006:0> I18n.locale = :en_US
=> :en_US
irb(main):007:0> I18n.localize Date.today, format: :date_month_year_concise
=> "01-03-15"

In views this method is aliased as #l, so you can use it like this (for Slim):

= l Date.today, format: :date_month_year_concise