Skip to content

Instantly share code, notes, and snippets.

@phughes
Created September 9, 2013 21:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phughes/6501822 to your computer and use it in GitHub Desktop.
Save phughes/6501822 to your computer and use it in GitHub Desktop.
A thread safe way to parse dates with arbitrary formats. NSDateFormatter is not thread safe. This method keeps a collection of formatters, one per thread per format, and creates/returns them in a thread safe manner. Caching formatter objects results in a significant speed improvement. On the simulator (2.4Ghz i5) we see the following numbers: Fo…
//
// NSDateFormatter+fbsThreadSafeFormatter.h
// NSDateAdditions
//
// Created by Patrick Hughes on 3/3/13.
// Copyright (c) 2013 Patrick Hughes. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSDateFormatter (fbsThreadSafeFormatter)
// NSDateFormatter is not thread safe. This method keeps a collection of formatters,
// one per thread per format, and creates/returns them in a thread safe manner.
/* Caching formatter objects results in a significant speed improvement.
On the simulator (2.4Ghz i5) we see the following numbers:
Formatting 10,000 date objects (single format, multiple threads):
Creating new formatter each time: 23.019063 seconds.
One formatter per thread: 1.352597 seconds.
*/
+ (NSDateFormatter*)fbsFormatterWithFormat:(NSString*)format;
+ (NSDateFormatter*)fbsFormatterWithFormat:(NSString*)format usingTimeZoneAbbreviation:(NSString*)abbreviation;
//
// NSDateFormatter+fbsThreadSafeFormatter.m
// NSDateAdditions
//
// Created by Patrick Hughes on 3/3/13.
// Copyright (c) 2013 Patrick Hughes. All rights reserved.
//
#import "NSDateFormatter+fbsThreadSafeFormatter.h"
#import <objc/runtime.h>
static char const * const formattersKey = "formattersKey";
static char const * const lockKey = "lockKey";
@implementation NSDateFormatter (fbsThreadSafeFormatter)
+ (NSDateFormatter*)fbsFormatterWithFormat:(NSString*)format
{
NSTimeZone *tz = [NSTimeZone localTimeZone];
return [self fbsFormatterWithFormat:format usingTimeZoneAbbreviation:[tz abbreviation]];
}
+ (NSDateFormatter*)fbsFormatterWithFormat:(NSString*)format usingTimeZoneAbbreviation:(NSString*)abbreviation
{
NSCache *formatters = objc_getAssociatedObject(self, formattersKey);
NSLock *lock = objc_getAssociatedObject(self, lockKey);
if (!formatters) {
formatters = [[NSCache alloc] init];
objc_setAssociatedObject(self, formattersKey, formatters, OBJC_ASSOCIATION_RETAIN);
}
if (!lock) {
lock = [[NSLock alloc] init];
objc_setAssociatedObject(self, lockKey, lock, OBJC_ASSOCIATION_RETAIN);
}
// Create a key for the formatter based on the current thread's address and the desired format.
NSString *key = [NSString stringWithFormat:@"%p%@%@", [NSThread currentThread], abbreviation, format];
[lock lock];
NSDateFormatter *formatter = [formatters objectForKey:key];
if (!formatter) {
formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:format];
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:abbreviation]];
[formatters setObject:formatter forKey:key];
}
[lock unlock];
return formatter;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment