Threadsafe Date Formatting

[OBSOLETE INFORMATION! SEE UPDATES!]

So let’s say you’ve got a project that involves a bunch of repetitive date manipulations, like merging multiple RSS feeds into a single timeline. And having done some timing, and read QA1480, you’re quite aware that

[NSDateFormatter alloc] is insanely expensive. If you’re doing it more than once, YOU’RE DOING IT WRONG.

So you’re doing it only once. And then you find that you start getting a disturbing number of crash reports with terminal lines like

Thread 9 Crashed:
3 libicucore.A.dylib 0x300cafa4 icu::DateFormat::parse(icu::UnicodeString const&, icu::ParsePosition&) const + 120

And that makes you remember, uh-oh … NSDateFormatter is thread-unsafe. Whoops. Well, that throws the above statement for a loop.

However, we can edit that to the actually correct

If you’re doing it more than once per thread, YOU’RE DOING IT WRONG.

by using thread local storage for something like

https://gist.github.com/alexcurylo/1b1147bc94e8bc59d84f

That should work out nicely for you.

UPDATES:

Note our earlier DateCalculations, Tip: NSDateFormatter Localization, Snippet: Ordinal Days, Snippet: NaturalDates, Code: NSDate (Helper), NSDateFormatter formatting

DateFormatter Reference:

On iOS 7 and later NSDateFormatter is thread safe.

On OS X v10.9 and later NSDateFormatter is thread safe so long as you are using the modern behavior in a 64-bit app.

On earlier versions of the operating system, or when using the legacy formatter behavior or running in 32-bit on OS X, NSDateFormatter is not thread safe and you therefore must not mutate a date formatter simultaneously from multiple threads.

If you’re parsing ISO-8601(JSON) dates, try Date Parsing Performance: NSDateFormatter vs. SQLite instead.

The Hit List Diary #21 – Lenient Date Parsing

FormatterKit has time intervals, and oodles of other goodies.

SwiftMoment: Open Source Swift Library For Working With Dates Inspired By Moment.js

Global Nerdy’s “How to work with dates and times in Swift” articles (so far):

Tempo: “Date and time manager for iOS/OSX written in Swift.”

if you are using NSDateFormatter -setDateFormat: without NSDateFormatter +dateFormatFromTemplate:options:locale:, you’re probably doing it wrong.

CVCalendarKit: “A wrapper around NSDate which provides a convenience way for dealing with dates.”

SwiftDate: “Easy NSDate Management in Swift.”

Timepiece: Open Source Swift Library Providing A Great Syntax For Working With Dates

Predictable Date Formatting “Apple specifically recommends using the “en_US_POSIX” locale [to parse an Internet-style date]”

Alex | July 5, 2011
  • Ole Begemann July 8, 2011 at 7:46 am
    From the screenshot you posted, it looks like -[NSDateFormatter init] is the expensive method, not alloc. Makes a lot more sense, too.
  • Alex July 8, 2011 at 8:07 am
    > init is the expensive method, not alloc Well, yes, but conventionally the two are closely associated so @nuthatch's comment is effectively accurate.
  • Marc May 8, 2012 at 9:56 am
    What if you need to use different formats in different parts of the app. Do you just get the dateWriter and reset the dateStyle or format string? If yes, could this potentially cause a thread unsafe condition, where you get the writer and set the format but before you use it another thread kicks in, calls a completion block on the main thread, the completion block then sets the format on this same date formatter. Thanks. Marc
    • Alex May 8, 2012 at 12:48 pm
      Safest to have one formatter per format string. They're not that big, just take a long time to set up.

Leave a Reply