Linux and displaying dates in ISO 8601 format…

If anyone knows me well, they know I have a passion for logical and rational standards. And of all the standards I have taken a shine to, one in particular sits at the top of the pile; head and shoulders above all others:


No, not the kind you go out on, but the way dates and times are written down and displayed.

My beef comes from a particular shortened variation that makes use of six digits separated by slashes. For example, can anyone determine what this date is:


Does it stand for the 2nd of August, 2006, as is used in Canada and most other countries around the world? Or does it stand for the 8th of February, 2006, as used by the United States (and ONLY the United States)? But wait — can it also be interpreted as the 6th of August, 2002 (popular in Europe)?

One string of numbers, three possible interpretations.

That is the reason why I try to introduce anyone who shows even the slightest interest to the ISO 8601 standard. This is an unambiguous standard, easy to read and impossible to misread:

2006-02-08 16:45

Now, how could anyone mistake that for anything other than a quarter before five in the afternoon on the 8th of February, 2006?

Plus, it has the benefit of being equally long when presented on a computer screen, no matter what date or time it is. As well, when you sort a list of dates by date, most computer programs do not need to guess which part of the grouping is the year, nor do they even have to realize that they are dealing with dates (the program doesn’t need to be “date aware”) — they just sort starting from left to right, and the dates end up being properly sorted by default.

This format is known as big-endian. That is, the big end is first in line. Why the year? Well, when looking at a date, you want your most important piece of information first. When dealing with a newspaper or sales receipt that says only “May 15th”, how useful is that? Not really, because the inevitable question is: “May 15th in what year?” By putting the year first, we put the most important piece of information first – what year it is in. And the year is really the most important thing — there are many possible May 15ths on newspapers and on sales receipts, but only one possible 2011. Every subsequent piece of information (month day 00-23 hour minute) narrows down the “window of time” by an additional gradation.

Now for Windows, changing the date and time to ISO 8601 is quite simple. You go into your Control Panel, choose Regional Options (Region and Language under Win7), and choose “additional settings” from the first tab. From there, you can change the short time to 24hr format, and switch the date from the horrid US-specific format to the yyyy-mm-dd format that is specified in ISO 8601. Heck, you can even change the two-year calendar interpretation to something higher (such as 2050), seeing as the default date isn’t very far in our future. And when you fire up Windows Explorer (what many people call “My Computer” — press and hold the Windows key between ctrl and alt, tap the letter e and let go of the win key), you will see that using ISO 8601 makes looking at the file dates much nicer and easier. Instead of a column with a ragged right, you have a very straight column of dates that is very easy to parse, or to visually and mentally sort.

Mac OSX is much the same, storing its values in System Preferences → International → Formats. A little dragging-and-dropping, and your dates and times will be in ISO 8601 format (be careful to preserve any spaces, or lack of them, between the dates!).

Unfortunately, Linux is a much different story. And a much more complex one.

Under Linux, pretty well each individual program can have its own way of dealing with date formats. Unlike Windows or Mac OSX, they do not draw many of their preferences from the system settings. However, there is one place where having properly formatted dates makes my life much easier:

The terminal.

As an old-school keyboardist, I tend to use Terminal for many of my operations. Whether it is rebooting the web server, creating a new file, editing text-based files with vi, or moving files around, I would rather use Terminal than any point-and-click GUI. It just ends up being much faster and much more efficient.

As such, when I type in the command

ls -l

to display the list of files and directories within the current working directory (similar to DOS’s dir command), what comes up often depends on the distro involved. Some, like several versions of Linux Mint (my workstation preference), default to ISO 8601 (thank you very much, Mint dev teams!!). Others, such as openSUSE (my server preference), decided to take a much more US-centric way of displaying file dates by showing it merely as “May 15”. Yup — not very useful. And not very helpful if I want to quickly filter (visually) by a particular month in a particular year — since any file more than 6 months old would be displayed (for example) as “May 15 2010” (for last year), my eyes (and cognative filter) would need to be constantly jumping over the day, switching back and forth between the year on the far right and interpreting the long-hand month on the far left. NOT a very efficient method!

Now, there is a way of telling the ls command to display dates in ISO format, by simply doing this:

ls -l --time-style=long-iso

but the problem with that is its sheer length! I often stumble over (and forget to include) the space between ls and the -l modifier that lists everything out in long format; doing the rest each and every time would simply be excrutiatingly painful!

There is also a way of modifying your shell to do this automagically, but there are problems with that as well. If you are using the bash shell (most distros are), you can edit your local file (for openSUSE this is /etc/bash.bashrc.local – Terminal reads this only when it starts up) to contain an alias for that entire string (base your own local file off of what the master file is called – for openSUSE the master file is bash.bashrc, so I created bash.bashrc.local). For example, you can add:

alias ls='ls -l --time-style=long-iso'

to the local file, but the problem is that you’ve lost your ability to use ls for quickly displaying files/folders in a multi-column layout without any additional information — it now acts as your alias because your alias is being invoked before the actual ls command. You could change the alias name to something else (dir, for example, if you have come from the Windows world), but then the system would no longer be pure. This would have to be an additional command you would have to remember, and the alias would be linked to only the ls -l command. And since there are so many darn modifiers for the ls command, you would have to create an alias for every possible combination of modifiers — a horrendous task!! And if anyone else had access to the machine as well, they would also need to learn these commands — UGH!

Thankfully, there is an easier way, through the use of environmental variables.

The ls command has got its own local file it can draw formatting from, and for openSUSE it also exists in the /etc/ directory: /etc/profile.local (once again, it may not exist, so use the sudo touch command to create it). Once you get it open, all you have to do is add a single line:

export TIME_STYLE=long-iso

Save the file, log out and back in, and presto — your ls -l commands will show proper ISO 8601 date formatting without having to clutter the system up with aliases! Plus, any other modifier that also shows the datetime will also show it in ISO 8601 format, no additional configuration necessary.

And that is why I prefer the elegant solutions over the quick and dirty ones: one line, and only one line, does the job of many. It is efficiency at its most refined.

Of course, that doesn’t mean that I’ll be getting rid of the dir alias just yet… since I use ls -l so much, and the other modifiers so infrequently, having a command that doesn’t have that awkward space-dash within it can be rather convenient.

Just sayin’.

Leave a Reply

Your email address will not be published. Required fields are marked *