开发者

NSDate dateFromString, how to parse 'around' UTC, GMT and User locale?

I parse some values from an xml file. There is a @"25-12-2010'T'23:40:00"string with the time and date and there is a string with the GMT offset like this @"+0200". So the above time is the 25. of December 23:40:00 in timeZone +0200 GMT. (or 21:40 UTC) I have lots of these dates with different GMT offsets. I have to display these dates as they are, i.e. They must not be changed to fit the locale of the user. So if time 1: is 22:45 +0500 then that is what I must show the user, even if the user is in a different timezone.

I have all sorts of trouble with displaying, calculating and parsing these strings.

If I use a dateFormatter and dateFromString the user specific GMT info will be included in the resulting NSDate meaning the above will be saved as 23:40:00 +0100 GMT because that is my phones setting and maybe 23:40:00 −0400 on a user from new New York's phone.

When I subsequently do subtraction, addition and comparisons between these dates I have to keep the GMT offset around and everything gets worse if the phone switches locale settings, from when the date was parsed to when the date is displayed...

Is there a way for me to extract this date from the string as UTC, then save it as an interval instead of an actual (timezone dependent) date. I know that is how dates are always saved internally. But I can't figure out开发者_高级运维 how to do it with the separate GMT string and taking into account the users locale.

Cheers


Use NSDateFormatter's setTimeZone:. You will also need to store the time zone offsets separately from the NSDate to later display the times in these time zones again.


Thank You Ole. I finally got my head around that NSDate and NSDateformatter are just abstract concepts and that a "date" is truly saved as "milliseconds or seconds since 1/1 2001" internally.

I did a "Proof of concept" to really understand it. Now it is suddenly very simple to write some categories on NSDate that makes sure that dates going in and coming out are correctly formatted, but all calculations are done on the raw UTC date.

- (void) testGMTDateParser {

    NSMutableArray *arrayDates = [NSMutableArray arrayWithCapacity:5];
    [self setParsedDates:arrayDates];

    NSMutableArray *arrayGMTOffsets = [NSMutableArray arrayWithCapacity:5];
    [self setParsedGMTOffsets:arrayGMTOffsets]; 

    NSString *date00    = @"2010-03-30T12:00:00";   
    NSString *GMT00     = @"-2";

    NSString *date01    = @"2010-03-30T12:00:00";   
    NSString *GMT01     = @"-1";

    NSString *date02    = @"2010-03-30T12:00:00";   
    NSString *GMT02     = @"+0";

    NSString *date03    = @"2010-03-30T12:00:00";   
    NSString *GMT03     = @"+1";

    NSString *date04    = @"2010-03-30T12:00:00";   
    NSString *GMT04     = @"+2";    

    NSArray *dateArray  = [NSArray arrayWithObjects:date00, date01, date02, date03, date04,nil];
    NSArray *GMTArray   = [NSArray arrayWithObjects:GMT00, GMT01, GMT02, GMT03, GMT04, nil];

    for (int i = 0; i < [dateArray count]; i++) {

        [self parseDateString:[dateArray objectAtIndex:i] withGMTString:[GMTArray objectAtIndex:i]];
    }   

}

Parse the Dates with regards to their respective GMT offset. This will make sure the UTC time saved internally is correct.

-(void) parseDateString:(NSString*) dateString withGMTString:(NSString*) GMTString {

    NSInteger hoursFromGMT      = [GMTString intValue]; 
    NSInteger secondsFromGMT    = (hoursFromGMT * 60 * 60);

    NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:secondsFromGMT];

    NSDateFormatter *dateFormatterGMTAware = [[NSDateFormatter alloc] init];
    [dateFormatterGMTAware setTimeZone:timeZone];
    [dateFormatterGMTAware setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
    NSDate *date = [dateFormatterGMTAware dateFromString:dateString];
    [dateFormatterGMTAware release];

    [self.parsedDates addObject:date];
    [self.parsedGMTOffsets addObject:[NSNumber numberWithInt:secondsFromGMT]];
}

Set up the NSDateformatter to print out the saved dates with regards to GMT offset. all dates can now be manipulated as UTC with no regards to GMT.

-(void) printOutDates {

    for (int i = 0; i < [self.parsedDates count]; i++) {

        NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:[[parsedGMTOffsets objectAtIndex:i] intValue]];

        NSDateFormatter *dateFormatterGMTAware = [[NSDateFormatter alloc] init];
        [dateFormatterGMTAware setTimeZone:timeZone];
        [dateFormatterGMTAware setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];

        NSLog(@"%@ in Original GMT", [dateFormatterGMTAware stringFromDate:[parsedDates objectAtIndex:i]]);
        NSLog(@"%@ in Local GMT\n\n", [parsedDates objectAtIndex:i]);
    }
}

2010-03-30 18:50:31.284 TimeZonePOC[39830:207] 2010-03-30 12:00:00 -0200 in Original GMT 2010-03-30 18:50:31.285 TimeZonePOC[39830:207] 2010-03-30 16:00:00 +0200 in Local GMT

2010-03-30 18:50:31.287 TimeZonePOC[39830:207] 2010-03-30 12:00:00 -0100 in Original GMT 2010-03-30 18:50:31.287 TimeZonePOC[39830:207] 2010-03-30 15:00:00 +0200 in Local GMT

2010-03-30 18:50:31.289 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0000 in Original GMT 2010-03-30 18:50:31.289 TimeZonePOC[39830:207] 2010-03-30 14:00:00 +0200 in Local GMT

2010-03-30 18:50:31.290 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0100 in Original GMT 2010-03-30 18:50:31.292 TimeZonePOC[39830:207] 2010-03-30 13:00:00 +0200 in Local GMT

2010-03-30 18:50:31.292 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0200 in Original GMT 2010-03-30 18:50:31.294 TimeZonePOC[39830:207] 2010-03-30 12:00:00 +0200 in Local GMT

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜