Date::DATE_FORMATS is quite helpful. It lets you do this:
Date.today.to_s(:custom)
with only this code in config/initializers/date_format.rb:
Date::DATE_FORMATS[:custom] = "%Y-%m-%d"
To do the same thing for DateTime instances, like created_at columns, use Time::DATE_FORMATS.
Time::DATE_FORMATS
To set the default format for either one, set DATE_FORMATS[:default]. This will cause <%= item.created_at %> to output “2011-08-16”, with no extra work from you.
We wanted to shorten the “about 1 month ago” text in an information-rich table that was squeezing created_at data.

We can override distance_in_words with the i18n API (and, by extension, time_ago_in_words).
A quick change to config/locales/en.yml and we’re done:
en:
datetime:
distance_in_words:
less_than_x_seconds:
other: '1 minute'
half_a_minute: '1 minute'
less_than_x_minutes:
one: '1 minute'
x_minutes:
one: '1 minute'
other: '{{count}} minutes'
about_x_hours:
one: '1 hour'
other: '{{count}} hours'
about_x_months:
one: '1 month'
other: '{{count}} months'
about_x_years:
one: '1 year'
other: '{{count}} years'
over_x_years:
one: 'over 1 year'
other: 'over {{count}} years'
The result:

You can see other options in svenfuchs/i18n.
Written by Dan Croak.
This is how I unit tested a view helper to format a date range in a view.
I wrote the interface for the view helper I wanted, but which did not exist yet:
= format_date_range(course.date_range)
The outer integration tests (not shown) failed with NoMethoError: format_date_range.
I generated a new helper file:
script/generate helper date_time
It produced:
# app/helpers/date_time_helper.rb
module DateTimeHelper
end
# test/unit/helpers/date_time_helper_test.rb
require 'test_helper'
class DateTimeHelperTest < ActionView::TestCase
end
I wrote the unit test:
should 'format date range on same day' do
eight_oclock = DateTime.new(2009, 10, 12, 8)
nine_oclock = DateTime.new(2009, 10, 12, 9)
date_range = eight_oclock..nine_oclock
expected = 'October 12, 2009'
assert_equal expected, format_date_range(date_range)
end
This style is flat test structure, intention-revealing temporary variables, respect an 80-character line limit.
I made it pass:
def format_date_range(date_range)
first = date_range.first
last = date_range.last
if same_day?(first, last)
"#{first.to_s(:month_day)}, #{first.year}"
end
end
private
def same_day?(date_one, date_two)
date_one.day == date_two.day
end
Like the test, I used intention-revealing temporary variables and a private method for a more expressive question in the conditional.
I wrote another test case:
should 'format date range on different days of same month' do
monday = DateTime.new(2009, 10, 12)
tuesday = DateTime.new(2009, 10, 13)
date_range = monday..tuesday
expected = 'October 12-13, 2009'
assert_equal expected, format_date_range(date_range)
end
I made it pass:
def format_date_range(date_range)
# ...
elsif same_month?(first, last)
"#{first.to_s(:month_day)}-#{last.day}, #{last.year}"
end
end
private
def same_month?(date_one, date_two)
date_one.month == date_two.month
end
Rails date and time formatting is done in locales:
en:
date:
formats:
long: ! '%B %d, %Y'
month_day: ! '%B %d'
short: ! '%b %d'
I wrote another test case:
should 'format date range on days of different months' do
october = DateTime.new(2009, 10, 31)
november = DateTime.new(2009, 11, 1)
date_range = october..november
expected = 'October 31-November 01, 2009'
assert_equal expected, format_date_range(date_range)
end
I made it pass:
else
"#{first.to_s(:month_day)}-#{last.to_s(:month_day)}, #{last.year}"
end
I wanted to remove the leading zero sucks. We could use `%e instead of %d, which replaces the leading zero with a space:
expected = "October 31-November 1, 2009"
That makes the test look a little ugly but since the output will be HTML, the extra space is fine.
Make it pass:
month_day: ! '%B %e'
Written by Dan Croak.