There is no single-line method for converting between formatting date strings and date objects in Cocoa — the API opts for flexibility rather than simplicity. Unfortunately, this combines with documentation that omits, misdirects and occasionally misinforms, making NSDateFormatter one of the more confusing classes for new Cocoa programmers. In this post, I'll try to address some of the documentation issues and I'll present some methods that will turn NSDate into a formatted string or convert between date strings in a single method.
Default, locale-based date formatting
NSDateto reduce it:
timeStringWithStyle:method by replacing the
dateStringWithStyle:method with a
dateStringWithProjectStylemethod that returns the appropriately configured string for use throughout your program. One of your projects might use
NSDateFormatterLongStyleand the next might use a totally customized format (as I'll describe in the next sections) but you as a programmer can still invoke
dateStringWithProjectStyleeverywhere you need a string from an
Date formatting documentation issues
NSDateFormatteris very simple to use and yet it repeatedly baffles new users. I don't think this is really the fault of the API as much as the history behind it and the effect that it has had on the documentation.
NSDateFormatterBehavior10_4being the only date formatting you should ever use and the only style that should exist in the documentation, Apple's documentation has the following quirks:
- The actual syntax for
NSDateFormatterBehavior10_4is never given in the documentation and you can easily miss the links to Unicode Standard (tr35) which describe it.
- A majority of the pages in the date formatting documentation seem concerned with the old
NSDateFormatterBehavior10_0style formatter behavior even though this is functionally deprecated.
- The documentation for
NSDateFormatterBehavior10_0is the default style but it is actually
NSDateFormatterBehavior10_4in Leopard and iPhoneSDK2.0.
NSDateFormatterAPI reference page:
iPhone OS Note: iPhone OS supports only the modern 10.4+ behavior. 10.0-style methods and format strings are not available on iPhone OS.
NSDateFormatterBehavior10_0style is completely meaningless — you can't use
NSDateFormatterBehavior10_0at all on the iPhone.
NSDateFormatterBehavior10_0will work in the simulator, causing headaches when code suddenly stops working on the device.
NSDateFormatterBehavior10_0, it is deprecated for all practical purposes so you probably shouldn't. Annoyingly, since the documentation still claims
NSDateFormatterBehavior10_0is the default, you should explicitly set the formatter behavior to
NSDateFormatterBehavior10_4to remain safe — at least until the documented default is updated to formally match the actual default.
Date formatting syntax
|y||Year||1, 2 or 4 'y's will show the value, 2 digit zero-padded value or 4 digit zero-padded value respectively|
|M||Month||1, 2, 3, 4 or 5 'M's will show the value, 2 digit zero-padded value, short name, long name or initial letter months|
|d||Day of Month||1 or 2 'd's will show the value or 2 digit zero-padded value representation respectively.|
|E||Weekday||1, 2, 3, 4 or 5 'e's will show the value weekday number, 2 digit zero-padded value weekday number, short name, long name or initial letter respectively. Weekday numbers starts on Sunday. Use lowercase 'e' for weekday numbers starting on Monday.|
|a||AM or PM||No repeat supported|
|h||Hour||1 or 2 'h's will show the value or 2 digit zero-padded value representation respectively. Use uppercase for 24 hour time.|
|m||Minute||1 or 2 'm's will show the value or 2 digit zero-padded value representation respectively.|
|s||Second||1 or 2 's's will show the value or 2 digit zero-padded value representation respectively.|
|z||Timezone||1, 2, 3 or 4 'z's will show short acronym, short name, long acronym, long name respectively. Use uppercase to show GMT offset instead of name — 1 or 2 digit zero-padded values shows GMT or RFC 822 respectively.|
Date string transcoding
NSDateFormatterclass is just for parsing and formatting strings. You shouldn't use it to build dates from their components or to decompose dates into components. For that task, use
NSCalendar. It's a little outside the scope of this post but since I know it will come up, here's how to set an
NSDateto the 26th of May, 2009 using