iPhone4 iOS5 [[NSTimeZone localTimeZone] daylightSavingTimeOffset] не подходит для перехода на летнее время? - PullRequest
1 голос
/ 10 ноября 2011

Я живу в восточном часовом поясе США (EST), и пару недель назад началась летняя экономия.Я тестировал некоторый мой предыдущий код, который работал (предположительно) нормально и заметил, что вычисления второго дня выполняются на 1 час раньше.

вот код, который я использую для тестирования:

 int  gmtOffset =  [[NSTimeZone localTimeZone] secondsFromGMT];
 int daylightOffset =  [[NSTimeZone localTimeZone] daylightSavingTimeOffset];

  int daySeconds =  ((int)([date timeIntervalSinceReferenceDate]+gmtOffset+daylightOffset))%(86400+1);

 NSLog(@"Day seconds: %i", daySeconds);

Результат на 3600 секунд меньше ожидаемого значения.Параметр daylightOffset равен 0. Как правильно получить смещение дневного света для часового пояса, в котором находится пользователь?NSDateFormatter анализирует дату правильно, поэтому он должен знать что-то, что NSTimeZone не сообщает мне.

Спасибо!

Ответы [ 3 ]

5 голосов
/ 17 марта 2013

[localTime secondsFromGMT] возвращает истинное время по Гринвичу, включая летнее время, вы можете получить само смещение на [localTime daylightSavingTimeOffset]

1 голос
/ 23 марта 2013

Это, кажется, повторяющаяся проблема для много ( меня включили ) и после того, как вытащилмои волосы слишком длинные, я наконец решил проблему.

Предположения, на которые опирается этот код, таковы:

  1. вас интересуют даты, а не время
  2. вы хотите, чтобы ваши вычисления даты не обращали внимания на любое летнее время
  3. вам нужно достаточно простое строковое представление даты, чтобы вы могли сохранить ее.

Для достижения1. Я использую уникальный экземпляр NSCalendar, который инициализируется в григорианском, GMT Это также служит 2.

для 3. NSDateFormatter инициализируется как уникальным календарем , так и его часовым поясом.Установка часового пояса для модуля форматирования на часовой пояс календаря, который в противном случае использовался для расчета, была ключом ко всем возникшим у меня проблемам!

Это всегда должно быть верно (предположим, что приведенный ниже код является частью класса DateModel):

NSDate * today = [DateModel normalize: [NSDate date]] ;
NSString*todayS= [DateModel dateToString: today] ;
BOOL alwaysTrue=[[DateModel normalize: [NSDate date]] isEqual: [DateModel stringToDate: todayS]] ; 

Вот код:

+ (NSDate *) normalize: (NSDate *) date {
    NSDateComponents * comps = [[DateModel calendar] components:NSYearCalendarUnit
                                                            |   NSMonthCalendarUnit
                                                            |   NSDayCalendarUnit
                                                            |   NSHourCalendarUnit
                                                            |   NSMinuteCalendarUnit
                                                            |   NSSecondCalendarUnit
                                                       fromDate:date] ;

    [comps setHour:0] ;
    [comps setMinute:0] ;
    [comps setSecond:0] ;

    NSDate * dateOnly = [[DateModel calendar] dateFromComponents:comps] ;

    return dateOnly ;
}

+ (NSCalendar *) calendar {
    static NSCalendar * calendar = nil ;
    if (calendar == nil) {
        calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] ;
        calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"GMT"] ;
    }
    return calendar ;
}

+ (NSDateFormatter *) dateFormatter {
    static NSDateFormatter * formatter = nil ;
    if (formatter == nil) {
        formatter = [[NSDateFormatter alloc] init] ;
        [formatter setCalendar:[self calendar]] ;          // <- This is
        [formatter setTimeZone:[self calendar].timeZone] ; // <- critical
        [formatter setDateFormat:@"yyyyMMdd"] ;
    }
    return formatter ;
}

+ (NSDate *) dateFromString: (NSString *) stringDate {
    return [DateModel normalize: [[DateModel dateFormatter] dateFromString:stringDate]] ;
}

+ (NSString *) stringFromDate: (NSDate *) date {
    return [[DateModel dateFormatter] stringFromDate:[DateModel normalize: date]] ;
}

Надеюсь, это кому-нибудь поможет!

0 голосов
/ 23 июля 2012

Если вы хотите определить количество секунд с полуночи, вы можете использовать компоненты даты. Этот код корректируется для перехода на летнее время.

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone localTimeZone]];

NSDateComponents *comps = [calendar components:NSHourCalendarUnit|NSMinuteCalendarUnit| NSSecondCalendarUnit
                                      fromDate:[NSDate date]];
NSInteger time = [comps hour] * 3600 + [comps minute] * 60 + [comps second];

NSLog(@"Day seconds: %i", time);
...