Time for strftime

The strftime function is a common way for programmers to convert a computer time into a human-readable string. You can pronounce it “string-f-time”, “string-from-time”, or “string-format-time”. While Ruby and PHP each have their own implementation, the function is actually part of the Unix open spec. That’s great news for developers because it means that we can reuse the formatting techniques in any language. I’ve also found that the Ruby/Rails docs are a little lacking and you might not have known that there were more options available. Since it’s not just for Ruby, we don’t have to rely on them as our sole source of information.
Keep reading and I’ll show you how to use strftime, give you a full list of format codes (downloadable even), and demonstrate a useful helper function for working around one of the quirks of strftime.
Unix timestamp
When we talk about “time”, we are actually talking about the date and time, not just the time of day. Time is stored internally as the number of seconds (and microseconds) since the Unix Epoch started on January 1, 1970 00:00 UTC. UTC stands for Universal Time Coordinated and is basically the same as GMT or Greenwich Mean Time. This count of seconds is called the Unix timestamp. (Something to keep in mind: due to technical reasons, some computers and databases act a little funky with dates before January 1, 1970 and after January 19, 2038.)
How to Use strftime
The strftime function takes a time expressed as a Unix timestamp and uses a format string to determine how it should output the time as a more readable version. The format string consists of formatting codes and ordinary characters. All ordinary characters are output as-is. Formatting codes consist of a percent sign (%) plus one character. Each code gives a format instruction. We’ll look at all the codes in a second, but first, here’s an example of a format string to illustrate how ordinary characters and codes can be mixed together.
timestamp = Time.now()
timestring = timestamp.strftime("The date is %m/%d/%y")
# timestring will be: "The date is 05/16/07"
$timestamp = time();
$timestring = strftime("The date is %m/%d/%y", $timestamp);
// $timestring will be: "The date is 05/16/07"
Easy enough, right? Everything with a % is a code that gets replaced by some part of the time. For example, %y will output the last two digits of the year in the final string. Every other character in the format string (those without the %) passes through unchanged. You can pull a time from a database, use form data to assemble it, or add or subtract from the current time to get it. Then when you are ready to output the results to the browser, strftime is all you need to make it look nice. The only thing missing is a list of the formatting codes so that we can customize the date and time to look exactly like we want.
Formatting Codes
The listings for strftime on Ruby Central and in the Ruby on Rails Core Library list most but not all of the possibilities. The strftime documentation on PHP.net is better and the Open Group’s Unix spec is probably the most authoritative. Because it’s Unix, it is handy to remember that you can just pop open a Unix or Linux command line and type ‘man strftime’ to get a quick format code refresher.
At the bottom of this post is a table that I put together which has all of the formatting codes. I’ve sorted them into categories based on year, month, day, etc. I find it easier to reference this way. The online listings previously mentioned will have it alphabetically by code. I’ve also put the same formating code list into a handy reference PDF that you can download.
Some Quirks to Work Through
Either download the PDF or jump to the bottom of this post, review the codes, then come back here. There are a couple of problems I want to point out to you. Find %m, %e, and %l. Notice that %m outputs the month as a number, but there’s not an option like %e and %l which will display the month with no leading 0. January can be formated as ‘01′ but not ‘1′. And %e and %l take the liberty of adding a space in place of the zero. (And %e and %l are notable omissions from the Ruby on Rails documentation.) Because it took me awhile to look past the Rails docs and to realize that the underlying strftime function is univeral Unix, I wrote up a function in Rails that would remove leading zeros. Even after I found out that I could use %e and %l, my function still proved to be useful for getting around the other problems. I hope it will help you too.
What I needed was a way to find the extra zeros before a single-digit month or day name and remove them (instead of putting in a space). My solution was to include a special character in the format string right before the possible zero. It can be any character as long as it is not likely to be in your output string, but I picked as asterisk. When I apply my function to the strftime output, it first removes any occurrence of ‘*0′. Then it removes any remaining asterisks, because those are in front of other numbers we want to leave unchanged.
def strip_zeros_from_date(marked_date_string)
cleaned_string = marked_date_string.gsub('*0', '').gsub('*', '')
return cleaned_string
end
timestamp = Time.now()
timestring = timestamp.strftime("The date is *%m/*%d/%y")
output = strip_zeros_from_date(timestring)
It’s a hack but it solves both problems of strftime. I get a string with no leading zeros and also without spaces in place of the zeros. I put it into ApplicationHelper and then I can call it from any view. You could do the same thing in PHP.
function strip_zeros_from_date( $marked_date_string ) {
$cleaned_string = str_replace('*', '', str_replace('*0', '', $marked_date_string));
return $cleaned_string;
}
$timestamp = time();
$timestring = strftime("The date is *%m/*%d/%y", $timestamp);
$output = strip_zeros_from_date($timestring);
I haven’t needed this technique for anything besides removing those pesky zeros, but you could easily “tag” any part of the format string and then search for the tag and modify it to suit your purposes. (Maybe swap in HTML tags or do something with Textile markup.) I also see that it could be made more flexible by allowing users to specify the “tag” character in the function parameters but use the astrisk as a default. But I’ll leave further improvements up to you.
strftime Format Codes
Year |
Example | |
| %Y | year with century | 2007 |
| %y | year without century | 07 |
| %C | century number (year divided by 100) | 20 |
Month |
Example | |
| %B | full month name | January |
| %b | abbreviated month name | Jan |
| %h | same as %b | Jan |
| %m | month as number | (01-12) |
Week |
Example | |
| %U | week number of the year, Sunday as first day of week | (00-53) |
| %W | week number of the year, Monday as first day of week | (00-53) |
Day |
Example | |
| %A | full weekday name | Wednesday |
| %a | abbreviated weekday name | Wed |
| %d | day of the month | (01-31) |
| %e | day of the month, single digits preceded by space | ( 1-31) |
| %j | day of the year | (001-366) |
| %w | weekday as a number, with 0 representing Sunday | (0-6) |
| %u | weekday as a number, with 1 representing Monday | (1-7) |
Time |
Example | |
| %H | hour (24-hour clock) | (00-23) |
| %k | hour (24-hour clock); single digits preceded by space | ( 0-23) |
| %I | hour (12-hour clock) | (01-12) |
| %l | hour (12-hour clock); single digits preceded by space | ( 1-12) |
| %M | minute | (00-59) |
| %S | seconds | (00-59) |
| %p | either AM or PM | AM |
| %Z | timezone name or abbreviation | EDT |
| %z | timezone offset from UTC | -0400 |
Summaries |
Example | |
| %D | date, same as %m/%d/%y | 05/16/07 |
| %v | date, same as %e-%b-%Y | 16-May-2007 |
| %F | date, same as %Y-%m-%d | 2007-05-16 |
| %R | time, 24 hour notation, same as %H:%M | 18:06 |
| %T | time, 24 hour notation, same as %H:%M:%S | 18:06:15 |
| %r | time, am/pm notation, same as %I:%M:%S %p | 06:06:15 PM |
Formatting |
||
| %n | newline character | |
| %t | tab character | |
| %% | percent character | |
Less common formats |
||
| %s | number of seconds since the Epoch, UTC | |
| %c | national date and time representation | |
| %+ | national date and time representation | |
| %x | national date representation | |
| %X | national time representation | |
| %G | year with century, starting on first Monday where week has 4 or more days. | |
| %g | year without century, starting on first Monday where week has 4 or more days. | |
| %V | week number of the year, starting on first Monday where week has 4 or more days. | |

July 19th, 2007 at 2:02 am
Much thanks for putting this together. Very helpful.
December 2nd, 2007 at 9:27 pm
[...] Posted in Ruby at 7:26 pm by Jim Halberg Not sure why this isn’t in the Ruby documentation (at least where I normally check) but the common annoyance of leading zeros on Time.strftime can be avoided simply by using “%l”. [...]