1. alloy020
  2. ISO 8601 parser/unparser

Commits

Peter Hosey  committed d59720a

Another 5× speed-up: Create and always use a single calendar per date formatter, instead of creating them and throwing them away, and make sure it always has our default time zone.

Comments (0)

Files changed (2)

File ISO8601DateFormatter.h Modified

View file
  • Ignore whitespace
  • Hide word diff
 	NSString *lastUsedFormatString;
 	NSDateFormatter *unparsingFormatter;
 
+	NSCalendar *calendar;
 	NSTimeZone *defaultTimeZone;
 	ISO8601DateFormat format;
 	unichar timeSeparator;
 	BOOL parsesStrictly;
 }
 
-@property(retain) NSTimeZone *defaultTimeZone;
+@property(nonatomic, retain) NSTimeZone *defaultTimeZone;
 
 #pragma mark Parsing
 

File ISO8601DateFormatter.m Modified

View file
  • Ignore whitespace
  • Hide word diff
 
 - (id) init {
 	if ((self = [super init])) {
+		calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
+		calendar.firstWeekday = 2; //Monday
+		calendar.timeZone = [NSTimeZone defaultTimeZone];
+
 		format = ISO8601DateFormatCalendar;
 		timeSeparator = ISO8601DefaultTimeSeparatorCharacter;
 		includeTime = NO;
 }
 
 @synthesize defaultTimeZone;
+- (void) setDefaultTimeZone:(NSTimeZone *)tz {
+	if (defaultTimeZone != tz) {
+		[defaultTimeZone release];
+		defaultTimeZone = [tz retain];
+
+		calendar.timeZone = defaultTimeZone;
+	}
+}
 
 //The following properties are only here because GCC doesn't like @synthesize in category implementations.
 
 	return [self dateComponentsFromString:string timeZone:outTimeZone range:NULL];
 }
 - (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange {
-	NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
-	calendar.firstWeekday = 2; //Monday
 	NSDate *now = [NSDate date];
 
 	NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
 	return [self dateFromString:string timeZone:outTimeZone range:NULL];
 }
 - (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange {
-	NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
-	calendar.firstWeekday = 2; //Monday
-
 	NSTimeZone *timeZone = nil;
 	NSDateComponents *components = [self dateComponentsFromString:string timeZone:&timeZone range:outRange];
 	if (outTimeZone)
 	if (includeTime)
 		dateFormat = [dateFormat stringByAppendingFormat:@"'T'%@", [self replaceColonsInString:ISO_TIME_FORMAT withTimeSeparator:self.timeSeparator]];
 
+	calendar.timeZone = timeZone;
+
 	if (dateFormat != lastUsedFormatString) {
 		[unparsingFormatter release];
 		unparsingFormatter = nil;
 	}
 
 	if (!unparsingFormatter) {
-		NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
-		calendar.firstWeekday = 2; //Monday
-
 		unparsingFormatter = [[NSDateFormatter alloc] init];
 		unparsingFormatter.formatterBehavior = NSDateFormatterBehavior10_4;
 		unparsingFormatter.dateFormat = dateFormat;
 		else
 			str = [str stringByAppendingFormat:ISO_TIMEZONE_OFFSET_FORMAT, offset / 60, offset % 60];
 	}
+
+	//Undo the change we made earlier
+	calendar.timeZone = self.defaultTimeZone;
+
 	return str;
 }
 
  *	http://personal.ecu.edu/mccartyr/ISOwdALG.txt
  */
 - (NSString *) weekDateStringForDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone {
-	NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
 	calendar.timeZone = timeZone;
 	NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSWeekdayCalendarUnit | NSDayCalendarUnit fromDate:date];