Peter Hosey avatar Peter Hosey committed 297b8da

Two calendars are better than one.

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.

Comments (0)

Files changed (2)

ISO8601DateFormatter.h

 	NSString *lastUsedFormatString;
 	NSDateFormatter *unparsingFormatter;
 
-	NSCalendar *calendar;
+	NSCalendar *parsingCalendar, *unparsingCalendar;
+
 	NSTimeZone *defaultTimeZone;
 	ISO8601DateFormat format;
 	unichar timeSeparator;

ISO8601DateFormatter.m

 
 @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;
 
 	[unparsingFormatter release];
 	[lastUsedFormatString release];
-	[calendar release];
+	[parsingCalendar release];
+	[unparsingCalendar release];
 
 	[super dealloc];
 }
 		[defaultTimeZone release];
 		defaultTimeZone = [tz retain];
 
-		calendar.timeZone = defaultTimeZone;
+		unparsingCalendar.timeZone = defaultTimeZone;
 	}
 }
 
 	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
 	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 {
 	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];
 		unparsingFormatter = [[NSDateFormatter alloc] init];
 		unparsingFormatter.formatterBehavior = NSDateFormatterBehavior10_4;
 		unparsingFormatter.dateFormat = dateFormat;
-		unparsingFormatter.calendar = calendar;
+		unparsingFormatter.calendar = unparsingCalendar;
 	}
 
 	NSString *str = [unparsingFormatter stringForObjectValue:date];
 	}
 
 	//Undo the change we made earlier
-	calendar.timeZone = self.defaultTimeZone;
+	unparsingCalendar.timeZone = self.defaultTimeZone;
 
 	return str;
 }
  *	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 {
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.