From 75964c2a92fc94bf4dc35de37b15d49681b0a950 Mon Sep 17 00:00:00 2001 From: Peter Hosey Date: Sat, 15 Oct 2011 16:04:52 -0700 Subject: [PATCH] Two calendars are better than one. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous 5× speed-up required assistance from the test program (setting the default output time zone to the time zone returned from an initial parse). Now it's official: ISO8601DateFormatter gets its 5× speed-up from calendar-caching without assistance from the test app. --- ISO8601DateFormatter.h | 3 ++- ISO8601DateFormatter.m | 37 ++++++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/ISO8601DateFormatter.h b/ISO8601DateFormatter.h index 0d4afab..725392c 100644 --- a/ISO8601DateFormatter.h +++ b/ISO8601DateFormatter.h @@ -39,7 +39,8 @@ extern unichar ISO8601DefaultTimeSeparatorCharacter; NSString *lastUsedFormatString; NSDateFormatter *unparsingFormatter; - NSCalendar *calendar; + NSCalendar *parsingCalendar, *unparsingCalendar; + NSTimeZone *defaultTimeZone; ISO8601DateFormat format; unichar timeSeparator; diff --git a/ISO8601DateFormatter.m b/ISO8601DateFormatter.m index 7444dd6..1afcaff 100644 --- a/ISO8601DateFormatter.m +++ b/ISO8601DateFormatter.m @@ -33,11 +33,17 @@ - (NSString *) weekDateStringForDate:(NSDate *)date timeZone:(NSTimeZone *)timeZ @implementation ISO8601DateFormatter +- (NSCalendar *) makeCalendarWithDesiredConfiguration { + NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; + calendar.firstWeekday = 2; //Monday + calendar.timeZone = [NSTimeZone defaultTimeZone]; + return calendar; +} + - (id) init { if ((self = [super init])) { - calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; - calendar.firstWeekday = 2; //Monday - calendar.timeZone = [NSTimeZone defaultTimeZone]; + parsingCalendar = [[self makeCalendarWithDesiredConfiguration] retain]; + unparsingCalendar = [[self makeCalendarWithDesiredConfiguration] retain]; format = ISO8601DateFormatCalendar; timeSeparator = ISO8601DefaultTimeSeparatorCharacter; @@ -51,7 +57,8 @@ - (void) dealloc { [unparsingFormatter release]; [lastUsedFormatString release]; - [calendar release]; + [parsingCalendar release]; + [unparsingCalendar release]; [super dealloc]; } @@ -62,7 +69,7 @@ - (void) setDefaultTimeZone:(NSTimeZone *)tz { [defaultTimeZone release]; defaultTimeZone = [tz retain]; - calendar.timeZone = defaultTimeZone; + unparsingCalendar.timeZone = defaultTimeZone; } } @@ -136,7 +143,7 @@ - (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSDate *now = [NSDate date]; NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease]; - NSDateComponents *nowComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:now]; + NSDateComponents *nowComponents = [parsingCalendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:now]; NSUInteger //Date @@ -594,9 +601,9 @@ - (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTi NSDateComponents *components = [self dateComponentsFromString:string timeZone:&timeZone range:outRange]; if (outTimeZone) *outTimeZone = timeZone; - calendar.timeZone = timeZone; + parsingCalendar.timeZone = timeZone; - return [calendar dateFromComponents:components]; + return [parsingCalendar dateFromComponents:components]; } - (BOOL)getObjectValue:(id *)outValue forString:(NSString *)string errorDescription:(NSString **)error { @@ -648,7 +655,7 @@ - (NSString *) stringFromDate:(NSDate *)date formatString:(NSString *)dateFormat if (includeTime) dateFormat = [dateFormat stringByAppendingFormat:@"'T'%@", [self replaceColonsInString:ISO_TIME_FORMAT withTimeSeparator:self.timeSeparator]]; - calendar.timeZone = timeZone; + unparsingCalendar.timeZone = timeZone; if (dateFormat != lastUsedFormatString) { [unparsingFormatter release]; @@ -662,7 +669,7 @@ - (NSString *) stringFromDate:(NSDate *)date formatString:(NSString *)dateFormat unparsingFormatter = [[NSDateFormatter alloc] init]; unparsingFormatter.formatterBehavior = NSDateFormatterBehavior10_4; unparsingFormatter.dateFormat = dateFormat; - unparsingFormatter.calendar = calendar; + unparsingFormatter.calendar = unparsingCalendar; } NSString *str = [unparsingFormatter stringForObjectValue:date]; @@ -677,7 +684,7 @@ - (NSString *) stringFromDate:(NSDate *)date formatString:(NSString *)dateFormat } //Undo the change we made earlier - calendar.timeZone = self.defaultTimeZone; + unparsingCalendar.timeZone = self.defaultTimeZone; return str; } @@ -694,14 +701,14 @@ - (NSString *) stringForObjectValue:(id)value { * http://personal.ecu.edu/mccartyr/ISOwdALG.txt */ - (NSString *) weekDateStringForDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone { - calendar.timeZone = timeZone; - NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSWeekdayCalendarUnit | NSDayCalendarUnit fromDate:date]; + unparsingCalendar.timeZone = timeZone; + NSDateComponents *components = [unparsingCalendar components:NSYearCalendarUnit | NSWeekdayCalendarUnit | NSDayCalendarUnit fromDate:date]; //Determine the ordinal date. - NSDateComponents *startOfYearComponents = [calendar components:NSYearCalendarUnit fromDate:date]; + NSDateComponents *startOfYearComponents = [unparsingCalendar components:NSYearCalendarUnit fromDate:date]; startOfYearComponents.month = 1; startOfYearComponents.day = 1; - NSDateComponents *ordinalComponents = [calendar components:NSDayCalendarUnit fromDate:[calendar dateFromComponents:startOfYearComponents] toDate:date options:0]; + NSDateComponents *ordinalComponents = [unparsingCalendar components:NSDayCalendarUnit fromDate:[unparsingCalendar dateFromComponents:startOfYearComponents] toDate:date options:0]; ordinalComponents.day += 1; enum {