views:

459

answers:

3

Forgive me as I'm new to Objective C.

I am getting back dates from a .NET webservice in the /Date(xxxxxxxxxxxxx-xxxx)/ format. I'm looking for some direction on how to best parse this into an NSDate object. I've tried using dateWithTimeIntervalSince1970 on it but it comes back with a date in the year 1969 for a date I know is in 2006.

Looking for some direction on the proper way to handle JSON dates.

Thanks in advance!

+5  A: 

Use an NSDateFormatter's dateFromString: method after setting the date format.

Dave DeLong
+1  A: 

As a .NET programmer learning Objective-C I had the same problem when I tried to consume a .Net WebService.

At first I thought I would be able to use the NSDateFormatter... I found a really good reference for it's symbols here, but I quickly realized that I needed to convert the number from milliseconds to seconds.

I wrote the code to do it... I'm still learning Obj-C but I dont think It should've been this hard...

- (NSDate *) getJSONDate{
 NSString* header = @"/Date(";
 uint headerLength = [header length];

 NSString*  timestampString;

 NSScanner* scanner = [[NSScanner alloc] initWithString:self];
 [scanner setScanLocation:headerLength];
 [scanner scanUpToString:@")" intoString:&timestampString];

 NSCharacterSet* timezoneDelimiter = [NSCharacterSet characterSetWithCharactersInString:@"+-"];
 NSRange rangeOfTimezoneSymbol = [timestampString rangeOfCharacterFromSet:timezoneDelimiter];

 [scanner dealloc];

 if (rangeOfTimezoneSymbol.length!=0) {
  scanner = [[NSScanner alloc] initWithString:timestampString];

  NSRange rangeOfFirstNumber;
  rangeOfFirstNumber.location = 0;
  rangeOfFirstNumber.length = rangeOfTimezoneSymbol.location;

  NSRange rangeOfSecondNumber;
  rangeOfSecondNumber.location = rangeOfTimezoneSymbol.location + 1;
  rangeOfSecondNumber.length = [timestampString length] - rangeOfSecondNumber.location;

  NSString* firstNumberString = [timestampString substringWithRange:rangeOfFirstNumber];
  NSString* secondNumberString = [timestampString substringWithRange:rangeOfSecondNumber];

  unsigned long long firstNumber = [firstNumberString longLongValue];
  uint secondNumber = [secondNumberString intValue];

   NSTimeInterval interval = firstNumber/1000;

  return [NSDate dateWithTimeIntervalSince1970:interval];
 }

 unsigned long long firstNumber = [timestampString longLongValue];
 NSTimeInterval interval = firstNumber/1000;

 return [NSDate dateWithTimeIntervalSince1970:interval];
}

Hopefully someone can provide a better Obj-C solution. If not I may keep this or look for a way to change the serialization format in .NET

EDIT:

About that JSON DateTime format... If you have any control on the service it would probably be best to convert the date to a string in your DataContract objects.

Formatting to RFC1123 seems like a good idea to me right now. As I can probably pick it up easily using a NSDateFormatter.

Quote from Rick Strahl

There's no JavaScript date literal and Microsoft engineered a custom date format that is essentially a marked up string. The format is a string that's encoded and contains the standard new Date(milliseconds since 1970) value.

AngrySpade
Thanks for the answer. I basically took the same approach you did. It feels like a hack and I wish there was a cleaner solution, but oh well it works for now.
+2  A: 

I was in the same boat whilst using json-framework which doesn't support the date format as it's not official JSON. My source is from an API built using JSON.Net. This is what I came up with:

- (NSDate*) getDateFromJSON:(NSString *)dateString
{
    // Expect date in this format "/Date(1268123281843)/"
    int startPos = [dateString rangeOfString:@"("].location+1;
    int endPos = [dateString rangeOfString:@")"].location;
    NSRange range = NSMakeRange(startPos,endPos-startPos);
    unsigned long long milliseconds = [[dateString substringWithRange:range] longLongValue];
    NSLog(@"%llu",milliseconds);
    NSTimeInterval interval = milliseconds/1000;
    return [NSDate dateWithTimeIntervalSince1970:interval];
}

I don't have the appended portion in the date format that you do so I haven't dealt with that like the answer above. No error catching either, it's all new to me at this point.

toxaq