2012-07-31

JSON, .NET and NSDate Redux

Here’s a version of my JSON date to NSDate conversion function updated to convert correctly to the local timezone.


/**
 * Converts a .NET JSON date in the format "/Date(x)/" to an NSDate object.
 * @param string The NSString to convert.
 * @return the NSDate object.
 */
(NSDate*)jsonStringToNSDate(NSString* string) {

    if (string == nil) return nil;

    // If we encounter .NET's minimum date value we treat it as nil.
    if ([string isEqualToString:@"/Date(-59011459200000)/"]) return nil;

    // Extract the numeric part of the date.  Dates should be in the format
    // "/Date(x)/", where x is a number.  This format is supplied automatically
    // by JSON serialisers in .NET.
    NSRange range = NSMakeRange(6, [string length] - 8);
    NSString* substring = [string substringWithRange:range];

    NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
    NSNumber* milliseconds = [formatter numberFromString:substring];

    [formatter release];

    // NSTimeInterval is specified in seconds.  The value we get back from the
    // web service is specified in milliseconds.  Both values are since 1st Jan
    // 1970 (epoch).
    NSTimeInterval seconds = [milliseconds longLongValue] / 1000.0;

    seconds += [[NSTimeZone localTimeZone] secondsFromGMT];

    return [NSDate dateWithTimeIntervalSince1970:seconds];
}

Edit: Fixed to return milliseconds as the fractional part of the “seconds” value.

2012-01-24

JSON, .NET and NSDate

If you’re trying to access a JSON web service created using .NET from an iOS device, you’ve probably discovered that dates are produced in a less than useful format:

/Date(1233423345345)/

The rationale for the date format can be found here, but it’s basically a call to the JavaScript Date object constructor. The numeric value represents the number of milliseconds since 1970-01-01.

Below I’ve added a handy Objective-C function that will extract the value and return an NSDate object. Note that we’re losing accuracy by magnitudes as we translate from .NET DateTime objects (which measure time in ticks) to JavaScript Date objects (which measure time in milliseconds) and finally to iOS NSDate objects (which measure time in seconds).


/**
 * Converts a .NET JSON date in the format "/Date(x)/" to an NSDate object.
 * @param string The NSString to convert.
 * @return the NSDate object.
 */
(NSDate*)jsonStringToNSDate(NSString* string) {

    // Extract the numeric part of the date.  Dates should be in the format
    // "/Date(x)/", where x is a number.  This format is supplied automatically
    // by JSON serialisers in .NET.
    NSRange range = NSMakeRange(6, [string length] - 8);
    NSString* substring = [string substringWithRange:range];

    // Have to use a number formatter to extract the value from the string into
    // a long long as the longLongValue method of the string doesn't seem to
    // return anything useful - it is always grossly incorrect.
    NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
    NSNumber* milliseconds = [formatter numberFromString:substring];

    [formatter release];

    // NSTimeInterval is specified in seconds.  The value we get back from the
    // web service is specified in milliseconds.  Both values are since 1st Jan
    // 1970 (epoch).
    NSTimeInterval seconds = [milliseconds longLongValue] / 1000;

    return [NSDate dateWithTimeIntervalSince1970:seconds];
}