ISO 8601 date formatter

Description

ISO 8601 provides a standard unambiguous format (several, actually) for dates and times. Unfortunately, NSDateFormatter alone does not completely support ISO 8601; in particular, it does not support week dates or ordinal dates.

This came to my attention when I began writing a patch for Vienna to add support for the ttl element of RSS 2.0 and the updatePeriod, updateFrequency, and updateBase elements of RDF Site Summary 1.0's Syndication module (which it borrowed from Open Content Syndication). The latter prescribes a YYYY-MM-DDTHH:MM format for dates. Somehow, I got it into my head that it prescribed ISO 8601 format for dates (as opposed to only the YYYY-MM-DDTHH:MM format), which would have meant that NSDateFormatter wouldn't work.

So, that's why I wrote this parser. I won't need it for Vienna, since RSS 1.0 doesn't actually prescribe ISO 8601 format by name (simply one version of it, which should be perfectly doable with plain Cocoa date-formatting techniques). Adium, however, does use ISO 8601 format in its log format, and so this parser/unparser is being used in Adium X 1.0 and later.

Version history

0.7 — 2013-10-09

Cocoa Touch is now officially supported. 4bc0a08 5d95233

Added an Xcode project with static library targets. c847ddb 4bc0a08

stringFromObjectValue: now logs to the Console when you hand it a value that isn't an NSDate. Check your Console output after upgrading—you might have had a bug all this time without knowing! 4e05978

Added proper documentation in the header, compatible with appledoc. f17713f

Fixed nonsense date components/dates being returned when the input is not a valid date string. 288f757 93bb9df 0cb6442

Fixed a bug in unparsing where the time zone was wrong (#3). 0e355ee 8f8a2c3 (Thanks, Carl Lindberg)

Fixed a DST bug in unparsing where the time zone offset was computed in general rather than for the date being unparsed (#6). 5665132 (Thanks, Zachary West) 9e835c8 0d36057

(iOS) The class now purges its time zone cache automatically in response to a memory warning. You don't need to do that yourself, anymore, so the method to purge the caches is no longer public. 138e186 3224b32 a9b6973 3f3c3b8

Added support for strings that specify a fraction of a second. 1d3194b 0b0b1ea (Thanks, Luke Redpath)

Added support for non-ASCII time separator characters. 47d5035

Added support for a time zone separator. 8198f1b 3bd0c07 17c15ed (Thanks to Daniel Tull for the suggestion.)

iOS users can now tell the ISO 8601 date formatter class to drop its caches (which you should do when you receive a memory warning). 2bb1725914b1

Added a couple of command-line options to the calendar-format-unparser test tool. c644aadb2b14

The parser test tool now displays parsed dates in GMT rather than the local time zone. 788c1455ecb1

Added a test tool to test unparsing with the time included. a89a9a8b3d61

You can now “make analysis” to run the Clang Static Analyzer on the date formatter. b3dd33841f42

The test tools are now built using Clang. 0723d3aa6596

Earlier versions

Version 0.5 was a major rewrite of much of the code, especially the unparser. Previous versions were category additions to NSCalendarDate (which is now deprecated). It's all now a single subclass of NSFormatter, and the implementation now uses NSCalendar and friends instead of the “strongly discouraged” NSCalendarDate. This means that version 0.5 and later require Mac OS X 10.4 or later. However, I have not tested it on Tiger; if it is broken on Tiger, I welcome your patch to fix it.

Version 0.4 added the ability to specify a custom time separator character instead of ':'. This works on both the parsing and unparsing directions.

Repositories

This project used to be hosted in a Mercurial repository. The old Mercurial repository will never again be updated! It is frozen forever at 0.6. If you want to follow changes or contribute changes yourself, follow and/or clone the Git repo.

Thanks to Jonathan Wight for converting the old Mercurial repo to Git.

I provide the ISO 8601 date f,ormatter under a BSD license. For more information, see the file named LICENSE.txt that comes with it.