Skip to content

Milliseconds on iso8601TimestampToDateValueTransformer #4

@chadpod

Description

@chadpod

The dates I get back from our server (Django/Piston) are of this format:

"2013-11-13T05:33:02.965Z"

I wanted to not lose the milliseconds portion because my modified date attribute check was failing because I was seeing some sub-second date changes. I changed the iso8601TimestampToDateValueTransformer as follows:

static unsigned int const ISO_8601_MAX_LENGTH = 29;
...
/* Check for milliseconds */
double milliseconds = 0.f;
if ([inputValue length] == 24 && [inputValue hasSuffix:@"Z"] && [inputValue characterAtIndex:19] == '.') {
    NSString *millisecondsString = [inputValue substringWithRange:NSMakeRange(20, 3)];
    milliseconds = [millisecondsString doubleValue]/1000.f;
}

if (length == 24 && source[length - 1] == 'Z') {
    memcpy(destination, source, length - 1);
    strncpy(destination + length - 1, "+0000\0", 6);
} else if (length == 29 && source[26] == ':') {
    memcpy(destination, source, 26);
    memcpy(destination + 26, source + 27, 2);
} else if (length == 20 && source[length - 1] == 'Z') {
    memcpy(destination, source, length - 1);
    strncpy(destination + length - 1, "+0000\0", 6);
} else if (length == 25 && source[22] == ':') {
    memcpy(destination, source, 22);
    memcpy(destination + 22, source + 23, 2);
} else {
    memcpy(destination, source, MIN(length, ISO_8601_MAX_LENGTH - 1));
}

destination[sizeof(destination) - 1] = 0;

struct tm time = {
    .tm_isdst = -1,
};

strptime_l(destination, "%FT%T%z", &time, NULL);

time_t timeIntervalSince1970 = timegm(&time);
RKValueTransformerTestTransformation(timeIntervalSince1970 != -1, error, @"Failed transformation to date representation: time range is beyond the bounds supported by mktime");
*outputValue = [NSDate dateWithTimeIntervalSince1970:((double)timeIntervalSince1970 + milliseconds)];

One thing that jumped out at me was the original version was using mktime, and I was getting dates that were shifted into the future by the number of hours my local timezone was offset from UTC. Since all dates I get back from the server are UTC, using 'timegm' got me the correct date.

As all this C date parsing stuff is new to me, I was hoping to get some feedback on the above changes and maybe they are of some use to you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions