Почему мой часовой пояс не сохраняется в моем NSDate?

Я должен инициализировать объект NSDate из NSString в objective-c. Я делаю это так:

NSString *dateString = [[webSentence child:@"DateTime"].text stringByReplacingOccurrencesOfString:@"T" withString:@" "];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-mm-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Budapest"]];

NSDate *date = [[NSDate alloc] init];
date = [dateFormatter dateFromString:dateString];

Например: когда я пытаюсь использовать его со строковым значением @ "2011-01-02 17:49:54" Я получаю NSDate 2011-01-02 16:49:54 +0000. Как вы видите, разница между двумя значениями составляет один час. NSDate имеет неправильное значение, оно должно быть точно таким же, как я определил в моей строке в часовом поясе, установленном в dateFormatter. Кажется, он использует мою дату, определенную как строка в формате UTC, даже если я установил часовой пояс для "Европа/Будапешт". Как я могу исправить эту проблему?

Спасибо!

Ответ 1

Две вещи:

1) у вас есть ошибка в вашей строке формата даты. Вы должны использовать MM месяц, а не MM (нижний регистр мм в минутах)

2) после создания объекта NSDate вам необходимо использовать метод NSDateFormatter stringFromDate:, чтобы создать строку даты, локализованную в определенный часовой пояс. Если вы просто сделаете прямой NSLog() на объекте NSDate, он покажет дату как GMT по умолчанию (GMT на один час после Будапештского времени).

Ответ 2

NSDate хранит даты относительно стандартной контрольной даты. Из документов класса:

"Единственный примитивный метод NSDate, timeIntervalSinceReferenceDate, обеспечивает основу для всех других методов в интерфейсе NSDate. Этот метод возвращает значение времени относительно абсолютной контрольной даты - первого момента 1 января 2001 года, GMT".

NSDate сам по себе не имеет понятия о часовых поясах. Итак, NSDateFormatter поступил правильно: он конвертировал дату, в которой вы сказали, что имеет смещение по GMT (путем указания часового пояса) и дал вам "нормализованный" NSDate для этой даты.

Если вы хотите увидеть дату, представленную в часовом поясе Европа/Будапешт, используйте либо существующий формат даты (-stringFromDate:), либо соответствующий метод описания NSDate (например, -descriptionWithCalendarFormat: timeZone: locale:).

P.S.- Вам вообще не нужно выделять /init в своем коде, как написано. В не-ARC, который будет утечкой.

P.P.S.- Ваш формат даты неверен и дает бессмысленные результаты. Я пошел дальше и очистил ваш код следующим образом (проверено в ARC):

NSString *dateString = @"2011-09-02 17:49:54";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *tz = [NSTimeZone timeZoneWithName:@"Europe/Budapest"];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:tz];

NSDate *date = [dateFormatter dateFromString:dateString];
NSLog(@"%@", [dateFormatter stringFromDate:date]);
NSLog(@"%@", [date descriptionWithCalendarFormat:nil timeZone:tz locale:nil]);