#ios #objective-c #nsdateformatter #nscalendar #nstimezone
#iOS #objective-c #nsdateformatter #nscalendar #nstimezone
Вопрос:
Почему следующие отмеченные утверждения терпят неудачу? Я просто запускал этот модульный тест на хосте в Центральной Европе. Следовательно NSCalendar.currentCalendar.timeZone
, это CEST, то есть GMT 0200. NSDateComponents
возвращает этот часовой пояс, но другие его значения (для года и т.д.), По-видимому, относятся к GMT. Как я могу получить значения, относящиеся к CEST?
- (void)test {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mmZZZ";
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"CEST"];
XCTAssertEqual(2 * 60 * 60, dateFormatter.timeZone.secondsFromGMT, @"");
NSDate *time = [dateFormatter dateFromString:@"2014-01-01T00:00 0200"]; // midnight on a Wednesday
NSCalendar *calendar = NSCalendar.currentCalendar; // i.e. CEST
XCTAssertEqual(2 * 60 * 60, calendar.timeZone.secondsFromGMT, @"");
NSDateComponents *components = [calendar components: NSYearCalendarUnit |
NSMonthCalendarUnit |
NSDayCalendarUnit |
NSWeekdayCalendarUnit |
NSHourCalendarUnit |
NSMinuteCalendarUnit |
NSTimeZoneCalendarUnit
fromDate:time];
XCTAssertEqual(components.year, 2014, @""); // fails with 2013
XCTAssertEqual(components.month, 1, @""); // fails with 12
XCTAssertEqual(components.day, 1, @""); // fails with 31
XCTAssertEqual(components.weekday, 4, @""); // fails with 3 (Tuesday)
XCTAssertEqual(components.hour, 0, @""); // fails with 23
XCTAssertEqual(components.minute, 0, @""); // succeeds
XCTAssertEqual(components.timeZone.secondsFromGMT, 2 * 60 * 60, @""); // succeeds (CEST)
}
Ответ №1:
NSCalendar.currentCalendar.timeZone
сейчас CEST или GMT 02, потому что в вашем часовом поясе сейчас действует летнее время. Но в 2014-01-01 летнее время не было активным. Поэтому все преобразования для этой даты выполняются со смещением GMT 01.
Итак, вот что происходит в вашем случае:
- Строка «2014-01-01T00:00 0200» преобразуется в
NSDate
«2013-12-31 22:00:00 0000″, потому что вы явно указываете смещение GMT » 0200″ во входной строке. Таким образом, установкаdateFormatter.timeZone
значения «CEST» не имеет никакого эффекта. - В
NSDate
«2013-12-31 22:00:00 0000» преобразуется в компоненты даты, используя ваш текущий календарь. Поскольку смещение по Гринвичу для этой даты равно «GMT 0100», вы получаете компоненты даты, соответствующие «2013-12-31 23:00:00 0100».
Если вы выполняете вычисления с помощью
NSDate *time = [dateFormatter dateFromString:@"2014-01-01T00:00 0100"];
затем тест завершается успешно.