Printing a Date
Problem
You want to print a date object as a string.
Solution
If you just want to look at a date, you can call Time#to_s or Date#to_s and not bother with fancy formatting:
require 'date' Time.now.to_s # => "Sat Mar 18 19:05:50 EST 2006" DateTime.now.to_s # => "2006-03-18T19:05:50-0500"
If you need the date in a specific format, you'll need to define that format as a string containing time-format directives. Pass the format string into Time#strftime or Date#strftime. You'll get back a string in which the formatting directives have been replaced by the correpsonding parts of the Time or DateTime object.
A formatting directive looks like a percent sign and a letter: %x. Everything in a format string that's not a formatting directive is treated as a literal:
Time.gm(2006).strftime('The year is %Y!') # => "The year is 2006!"
The Discussion lists all the time formatting directives defined by Time#strftime and Date#strftime. Here are some common time-formatting strings, shown against a sample date of about 1:30 in the afternoon, GMT, on the last day of 2005:
time = Time.gm(2005, 12, 31, 13, 22, 33) american_date = '%D' time.strftime(american_date) # => "12/31/05" european_date = '%d/%m/%y' time.strftime(european_date) # => "31/12/05" four_digit_year_date = '%m/%d/%Y' time.strftime(four_digit_year_date) # => "12/31/2005" date_and_time = '%m-%d-%Y %H:%M:%S %Z' time.strftime(date_and_time) # => "12-31-2005 13:22:33 GMT" twelve_hour_clock_time = '%m-%d-%Y %I:%M:%S %p' time.strftime(twelve_hour_clock_time) # => "12-31-2005 01:22:33 PM" word_date = '%A, %B %d, %Y' time.strftime(word_date) # => "Saturday, December 31, 2005"
Discussion
Printed forms, parsers, and people can all be very picky about the formatting of dates. Having a date in a standard format makes dates easier to read and scan for errors. Agreeing on a format also prevents ambiguities (is 4/12 the fourth of December, or the twelfth of April?)
If you require 'time', your Time objects will sprout special-purpose formatting methods for common date representation standards: Time#rfc822, Time#httpdate, and Time#iso8601. These make it easy for you to print dates in formats compliant with email, HTTP, and XML standards:
require 'time' time.rfc822 # => "Sat, 31 Dec 2005 13:22:33 -0000" time.httpdate # => "Sat, 31 Dec 2005 13:22:33 GMT" time.iso8601 # => "2005-12-31T13:22:33Z"
DateTime provides only one of these three formats. ISO8601 is the the default string representation of a DateTime object (the one you get by calling #to_s). This means you can easily print DateTime objects into XML documents without having to convert them into Time objects.
For the other two formats, your best strategy is to convert the DateTime into a Time object (see Recipe 3.9 for details). Even on a system with a 32-bit time counter, your DateTime objects will probably fit into the 19012037 year range supported by Time, since RFC822 and HTTP dates are almost always used with dates in the recent past or near future.
Sometimes you need to define a custom date format. Time#strftime and Date#strftime define many directives for use in format strings. The big table below says what they do. You can combine these in any combination within a formatting string.
Some of these may be familiar to you from other programming languages; virtually all languages since C have included a strftime implementation that uses some of these directives. Some of the directives are unique to Ruby.
Formatting directive |
What it does |
Example for 13:22:33 on December 31, 2005 |
---|---|---|
%A |
English day of the week |
"Saturday" |
%a |
Abbreviated English day of the week |
"Sat" |
%B |
English month of the year |
"December" |
%b |
English month of the year |
"Dec" |
%C |
The century part of the year, zero-padded if necessary. |
"20" |
%c |
This prints the date and time in a way that looks like the default string representation of Time, but without the timezone. Equivalent to '%a %b %e %H:%M:%S %Y' |
"Sat Dec 31 13:22:33 2005" |
%D |
American-style short date format with two-digit year. Equivalent to "%m/%d/%y" |
"12/31/05" |
%d |
Day of the month, zero-padded |
"31" |
%e |
Day of the month, not zero-padded |
"31" |
%F |
Short date format with 4-digit year.; equivalent to "%Y-%m-%d" |
"2005-12-31" |
%G |
Commercial year with century, zero-padded to a minimum of four digits and with a minus sign prepended for dates BCE (see Recipe 3.11. For the calendar year, use %Y) |
"2005" |
%g |
Year without century, zero-padded to two digits |
"05" |
%H |
Hour of the day, 24-hour clock, zero-padded to two digits |
"13" |
%h |
Abbreviated month of the year; the same as "%b" |
"Dec" |
%I |
Hour of the day, 12-hour clock, zero-padded to two digits |
"01" |
%j |
Julian day of the year, padded to three digits (from 001 to 366) |
"365" |
%k |
Hour of the day, 24-hour clock, not zero-padded; like %H but with no padding |
"13" |
%l |
Hour of the day, 12-hour clock, not zero-padded; like %I but with no padding |
"1" |
%M |
Minute of the hour, padded to two digits |
"22" |
%m |
Month of the year, padded to two digits |
"12" |
%n |
A newline; don't use this; just put a newline in the formatting string |
" " |
%P |
Lowercase meridian indicator ("am" or "pm") |
"pm" |
%p |
Upper meridian indicator. Like %P, except gives "AM" or "PM"; yes, the uppercase P gives the lowercase meridian, and vice versa |
"PM" |
%R |
Short 24-hour time format; equivalent to "%H:%M" |
"13:22" |
%r |
Long 12-hour time format; equivalent to "%I:%M:%S %p" |
"01:22:33 PM" |
%S |
Second of the minute, zero-padded to two digits |
"33" |
%s |
Seconds since the Unix epoch |
"1136053353" |
%T |
Long 24-hour time format; equivalent to "%H:%M:%S" |
"13:22:33" |
%t |
A tab; don't use this; just put a tab in the formatting string |
" " |
%U |
Calendar week number of the year: assumes that the first week of the year starts on the first Sunday; if a date comes before the first Sunday of the year, it's counted as part of "week zero" and "00" is returned |
"52" |
%u |
Commercial weekday of the year, from 1 to 7, with Monday being day 1 |
"6" |
%V |
Commercial week number of the year (see Recipe 3.11) |
"52" |
%W |
The same as %V, but if a date is before the first Monday of the year, it's counted as part of "week zero" and "00" is returned |
"52" |
%w |
Calendar day of the week, from 0 to 6, with Sunday being day 0 |
"6" |
%X |
Preferred representation for the time; equivalent to "%H:%M:%S" |
"13:22:33" |
%x |
Preferred representation for the date; equivalent to "%m/%d/%y" |
"12/31/05" |
%Y |
Year with century, zero-padded to four digits and with a minus sign prepended for dates BCE |
"2005" |
%y |
Year without century, zero-padded to two digits |
"05" |
%Z |
The timezone abbreviation (Time) or GMT offset (Date). Date will use "Z" instead of "+0000" if a time is in GMT |
"GMT" for Time, "Z" for Date |
%z |
The timezone as a GMT offset |
"+0000" |
%% |
A literal percent sign |
"%" |
%v |
European-style date format with month abbreviation; equivalent to "%e-%b-%Y" |
31-Dec-2005 |
%+ |
Prints a Dateobject as though it were a Timeobject converted to a string; like %c, but includes the timezone information; equivalent to "%a %b %e %H:%M:%S %Z %Y" |
Sat Dec 31 13:22:33 Z 2005 |
Date defines two formatting directives that won't work at all in Time#strftime. Both are shortcuts for formatting strings that you could create manually.
If you need a date format for which there's no formatting directive, you should be able to compensate by writing Ruby code. For instance, suppose you want to format our example date as "The 31st of December". There's no special formatting directive tol print the day as an ordinal number, but you can use Ruby code to build a formatting string that gives the right answer.
class Time def day_ordinal_suffix if day == 11 or day == 12 return "th" else case day % 10 when 1 then return "st" when 2 then return "nd" when 3 then return "rd" else return "th" end end end end time.strftime("The %e#{time.day_ordinal_suffix} of %B") # => "The 31st of December"
The actual formatting string differs depending on the date. In this case, it ends up "The %est of %B", but for other dates it will be "The %end of %B", "The %erd of %B", or "The %eth of %B".
See Also
- Time objects can parse common date formats as well as print them out; see Recipe 3.2, "Parsing Dates, Precisely or Fuzzily," to see how to parse the output of strftime, rfc822, httpdate, and iso8661
- Recipe 3.11, "Handling Commercial Dates"