Спасибо, Оле. Я наконец понял, что NSDate
и NSDateformatter
просто абстрактны
концепции и что «дата» действительно сохраняется как «миллисекунды или секунды с 1 января 2001 года» внутри.
Я сделал «Доказательство концепции», чтобы действительно понять это. Теперь неожиданно очень просто записать некоторые категории в NSDate
, которые гарантируют, что даты, входящие и выходящие, правильно отформатированы, но все вычисления выполняются в исходную дату UTC.
- (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]];
}
}
Разобрать даты по их смещению по Гринвичу. Это обеспечит сохранение времени UTC
внутренне правильно.
-(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]];
}
Настройте NSDateformatter для печати сохраненных дат с учетом смещения по Гринвичу.
все даты теперь можно манипулировать как UTC без учета времени по Гринвичу.
-(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 в оригинальном GMT
2010-03-30 18: 50: 31.285 TimeZonePOC [39830: 207] 2010-03-30 16:00:00 +0200 по местному времени по Гринвичу
2010-03-30 18: 50: 31.287 TimeZonePOC [39830: 207] 2010-03-30 12:00:00 -0100 в оригинальном GMT
2010-03-30 18: 50: 31.287 TimeZonePOC [39830: 207] 2010-03-30 15:00:00 +0200 по местному времени по Гринвичу
2010-03-30 18: 50: 31.289 TimeZonePOC [39830: 207] 2010-03-30 12:00:00 +0000 в оригинальном GMT
2010-03-30 18: 50: 31.289 TimeZonePOC [39830: 207] 2010-03-30 14:00:00 +0200 по местному времени по Гринвичу
2010-03-30 18: 50: 31.290 TimeZonePOC [39830: 207] 2010-03-30 12:00:00 +0100 в оригинальном GMT
2010-03-30 18: 50: 31.292 TimeZonePOC [39830: 207] 2010-03-30 13:00:00 +0200 по местному времени GMT
2010-03-30 18: 50: 31.292 TimeZonePOC [39830: 207] 2010-03-30 12:00:00 +0200 в оригинальном GMT
2010-03-30 18: 50: 31.294 TimeZonePOC [39830: 207] 2010-03-30 12:00:00 +0200 по местному времени по Гринвичу