Skip to content

Instantly share code, notes, and snippets.

@mnbi
Created November 23, 2010 18:19
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mnbi/712238 to your computer and use it in GitHub Desktop.
Save mnbi/712238 to your computer and use it in GitHub Desktop.
convert a RFC3339 date string into a NSDate object
#import <Foundation/Foundation.h>
// convert a RFC3399 date (& time) into a NSDate object
// NOTE: This function ignores fractions of a second in the RFC3339
// representation.
NSDate *getDateObject(NSString *rfc3339)
{
// Date and Time representation in RFC3399:
// Pattern #1: "YYYY-MM-DDTHH:MM:SSZ"
// 1
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
// [Y|Y|Y|Y|-|M|M|-|D|D|T|H|H|:|M|M|:|S|S|Z]
//
// Pattern #2: "YYYY-MM-DDTHH:MM:SS.sssZ"
// 1 2
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
// [Y|Y|Y|Y|-|M|M|-|D|D|T|H|H|:|M|M|:|S|S|.|s|s|s|Z]
// NOTE: The number of digits in the "sss" part is not defined.
//
// Pattern #3: "YYYY-MM-DDTHH:MM:SS+HH:MM"
// 1 2
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
// [Y|Y|Y|Y|-|M|M|-|D|D|T|H|H|:|M|M|:|S|S|+|H|H|:|M|M]
//
// Pattern #4: "YYYY-MM-DDTHH:MM:SS.sss+HH:MM"
// 1 2
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
// [Y|Y|Y|Y|-|M|M|-|D|D|T|H|H|:|M|M|:|S|S|.|s|s|s|+|H|H|:|M|M]
// NOTE: The number of digits in the "sss" part is not defined.
// NSDate format: "YYYY-MM-DD HH:MM:SS +HHMM".
NSCharacterSet *setOfT = [NSCharacterSet characterSetWithCharactersInString:@"tT"];
NSRange tMarkPos = [rfc3339 rangeOfCharacterFromSet:setOfT];
if (tMarkPos.location == NSNotFound) return nil;
// extract date and time part:
NSString *datePart = [rfc3339 substringToIndex:tMarkPos.location];
NSString *timePart = [rfc3339 substringWithRange:NSMakeRange(tMarkPos.location + tMarkPos.length, 8)];
NSString *restPart = [rfc3339 substringFromIndex:tMarkPos.location + tMarkPos.length + 8];
// extract time offset part:
NSString *tzSignPart, *tzHourPart, *tzMinPart;
NSCharacterSet *setOfZ = [NSCharacterSet characterSetWithCharactersInString:@"zZ"];
NSRange tzPos = [restPart rangeOfCharacterFromSet:setOfZ];
if (tzPos.location == NSNotFound) { // Pattern #3 or #4
NSCharacterSet *setOfSign = [NSCharacterSet characterSetWithCharactersInString:@"+-"];
NSRange tzSignPos = [restPart rangeOfCharacterFromSet:setOfSign];
if (tzSignPos.location == NSNotFound) return nil;
tzSignPart = [restPart substringWithRange:tzSignPos];
tzHourPart = [restPart substringWithRange:NSMakeRange(tzSignPos.location + tzSignPos.length, 2)];
tzMinPart = [restPart substringFromIndex:tzSignPos.location + tzSignPos.length + 2 + 1];
} else { // Pattern #1 or #2
// "Z" means UTC.
tzSignPart = @"+";
tzHourPart = @"00";
tzMinPart = @"00";
}
// construct a date string in the NSDate format
NSString *dateStr = [NSString stringWithFormat:@"%@ %@ %@%@%@", datePart, timePart, tzSignPart, tzHourPart, tzMinPart];
NSDate *dateObj = [[NSDate alloc] initWithString:dateStr];
[dateObj autorelease];
return dateObj;
}
void testGetDateObject(NSString *rfc3339)
{
NSLog(@"----------------------------------------");
NSLog(@"RFC3339 Format: %@", rfc3339);
NSDate *date = getDateObject(rfc3339);
NSLog(@"NSDate object: %@", date);
NSString *dateFormat = @"%Y-%m-%d %H:%M:%S %z";
NSString *dateInDefaultTZ = [date descriptionWithCalendarFormat:dateFormat timeZone:nil locale:nil];
NSLog(@"Default TZ: %@", dateInDefaultTZ);
NSTimeZone *aTimeZone = [NSTimeZone timeZoneWithName:@"UTC"];
NSString *dateInUTC = [date descriptionWithCalendarFormat:dateFormat timeZone:aTimeZone locale:nil];
NSLog(@"UTC: %@", dateInUTC);
}
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
testGetDateObject(@"2010-11-22T12:34:56Z");
testGetDateObject(@"2010-11-22t12:34:56z");
testGetDateObject(@"2010-11-22T12:34:56.123Z");
testGetDateObject(@"2010-11-22t12:34:56.123z");
testGetDateObject(@"2010-11-22T12:34:56+09:00");
testGetDateObject(@"2010-11-22t12:34:56+09:00");
testGetDateObject(@"2010-11-22T12:34:56.123+09:00");
testGetDateObject(@"2010-11-22t12.34.56.123+09:00");
testGetDateObject(@"2010-11-22T12:34:56-05:00");
testGetDateObject(@"2010-11-22T12:34:56.123-05:00");
[pool drain];
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment