Формат NSDate, выводящий неверную дату

У меня есть NSString (например, «2011-04-12 19:23:39»), и что я сделал, чтобы отформатировать его в NSDate, было следующее:

[inputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSDate *date = [inputFormatter dateFromString:newDateString]; 

но что он выводит, когда я nslog дата:

2011-04-12 23:23:39 +0000

который составляет около 4 часов. Я что-то пропустил? Возможно, проблема с часовым поясом?

5 Solutions collect form web for “Формат NSDate, выводящий неверную дату”

NSDateFormatter использует текущий часовой пояс устройства, когда он создал объект NSDate. NSDate хранит дату / время в GMT. Поэтому по умолчанию NSLog выводит дату / время в GMT + 0. Итак, в коде нет ничего плохого. Теперь, если вы хотите вывести NSDate в текущий часовой пояс, вам придется использовать объект NSDateFormatter.

Короче говоря, датой возвращается GMT, если не указано иное. Вы можете установить часовой пояс, чтобы получить правильную дату. Если вы планируете использовать дату в приложении для установки чего-либо (например, localNotification time или Event), вам нужно будет сделать что-то особенное с датой, потому что если вы установите дату в iPhone, она будет установлена ​​как GMT и будет выключена на несколько часов. (в вашем случае 4 часа). Я делаю то, что я только что описал в одном из моих приложений.

Я сделал беспорядок, пытаясь заставить это работать правильно, не выходя из часов. Это была огромная PITA, чтобы разобраться, но теперь она работает. Я скопировал, вставил и отредактировал свой код для совместного использования. Опять же, его беспорядок, но он работает! PickerChanged получает информацию от UIDatePicker

Используя приведенный ниже код. Чтобы ответить на ваш вопрос, вы можете остановиться на «destinationDate». Это вернет вам исправленное время для вашего текущего часового пояса. Я просто предоставил дополнительный взнос, когда вы пытались использовать дату на телефоне где-то.

ПРИМЕЧАНИЕ. Для быстрого примера я помещаю напоминание о событии в ту же функцию, что и datepicker, вы НЕ хотите этого делать, иначе у вас будет много напоминаний, установленных каждый раз, когда колесики прокручиваются в datepicker.

Код ниже.

  - (void)pickerChanged:(id)sender { NSLog(@"value: %@",[sender date]); NSDate* date= [sender date]; NSDateFormatter *formatter=[[[NSDateFormatter alloc]init]autorelease]; [formatter setDateFormat:@"MM/dd/yyyy hh:mm:ss a"]; [formatter setTimeZone:[NSTimeZone systemTimeZone]]; [formatter setTimeStyle:NSDateFormatterLongStyle]; NSString *dateSelected =[formatter stringFromDate:date]; NSString *timeZone = [dateSelected substringFromIndex:12]; NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone]; //here we have to get the time difference between GMT and the current users Date (its in seconds) NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:date]; //need to reverse offset so its correct when we put it in the calendar correctedTimeForCalendarEvent = destinationGMTOffset + (2*(-1*destinationGMTOffset)); //date to enter into calendar (we will use the correctedTimeForCalendarEvent to correct the time otherwise it will be off by a few hours ) NSDate * destinationDate = [[[NSDate alloc] initWithTimeInterval:destinationGMTOffset sinceDate:date] autorelease]; NSDate * dateForReminder = destinationDate; // return destinationDate; NSLog(@"value: %@ - %@",destinationDate,dateForReminder); //DO NOT put this code in this same function this is for a quick example only on StackOverflow //otherwise you will have reminders set everytime the users scrolled to a different time //set event reminder //make sure to import EventKit framework EKEventStore *eventDB = [[[EKEventStore alloc] init]autorelease]; EKEvent *myEvent = [EKEvent eventWithEventStore:eventDB]; NSString * eventTitle = [NSString stringWithFormat:@"%@ - %@",app.dealerBusinessName,serviceOrComments.text]; myEvent.title = eventTitle; //double check date one more time NSLog(@"value: %@",destinationDate); //set event time frame (1 hour) the "initWithTimeInterval" is where we account for the users timezone by adding the correctedTime from GMT to the calendar time ( so its not off by hours when entering into calendar) myEvent.startDate = [[[NSDate alloc] initWithTimeInterval:correctedTimeForCalendarEvent sinceDate:destinationDate ]autorelease]; myEvent.endDate = [[[NSDate alloc] initWithTimeInterval:3600 sinceDate:myEvent.startDate]autorelease]; myEvent.allDay = NO; //set event reminders 1 day and 1 hour before myAlarmsArray = [[[NSMutableArray alloc] init] autorelease]; EKAlarm *alarm1 = [EKAlarm alarmWithRelativeOffset:-3600]; // 1 Hour EKAlarm *alarm2 = [EKAlarm alarmWithRelativeOffset:-86400]; // 1 Day [myAlarmsArray addObject:alarm1]; [myAlarmsArray addObject:alarm2]; myEvent.alarms = myAlarmsArray; [myEvent setCalendar:[eventDB defaultCalendarForNewEvents]]; NSError *err; [eventDB saveEvent:myEvent span:EKSpanThisEvent error:&err]; if (err == noErr) { //no error, but do not show alert because we do that below. } } 

Ваши данные и формат даты опускают спецификатор TimeZone. Так что-то вроде этого:

 [inputFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ssZ"]; 

Будет работать – Z является спецификатором часового пояса и будет анализировать как цифровые смещения, так и коды часовых поясов. Хотя в вашем случае, когда ваша дата ввода не имеет информации о TimeZone, она не будет работать.

Ваша правильная строка времени должна выглядеть как «2011-04-12 19:23:39 -0400» или «2011-04-12 19:23:39 EST»

В зависимости от того, откуда вы взяли дату, вы должны исправить это, чтобы получить полную дату, если вы не можете этого сделать, вам придется согласовать смещения часового пояса с сервером или просто «жесткий код» смещение часового пояса и добавить этот номер секунд до вашего NSDate.

Дата регистрируется как дата UTC, которую можно увидеть в конце +0000 . Формат даты, который вы используете для синтаксического анализа строки, предполагает ваш местный часовой пояс, который предположительно на 4 часа ниже UTC с летней экономией и стандартным -5 часов.

Используйте -[NSDateFormatter setTimeZone:] чтобы предоставить формат даты с информацией о часовом поясе. Вы можете использовать местный часовой пояс или если у вас есть фиксированный часовой пояс, связанный с информацией о дате, я рекомендую создать часовой пояс с именем (например, «Америка / Восток»), а не аббревиатурой (например, «EST» или «EDT»), поскольку имя не вносит эффект летнего времени в силу, но использует правильное смещение дневного света для этой даты в этом часовом поясе.

  • Пользовательский интерфейс UINavigationBar
  • Правильный способ выхода из приложения iPhone?
  • К ARC или не к ARC? Каковы плюсы и минусы?
  • Как установить жирный шрифт и курсив на UILabel iPhone / iPad?
  • Что делает флаг компоновщика -all_load?
  • Одновременные распознаватели жестов в Iphone SDK
  • Как я могу изменить NSArray в Objective-C?
  • Как работает новый механизм автоматического подсчета ссылок?
  • Прокрутка UITableView внутри UIScrollView
  • Почему вы используете символ подчеркивания для переменной экземпляра, но не соответствующее ему свойство?
  • Как получить текущее название города?
  • Давайте будем гением компьютера.