Не могу отформатировать время правильно - PullRequest
1 голос
/ 15 мая 2019

У меня есть следующий метод, который берет данное Время (в UTC) в качестве параметра и преобразует его в текущее время, скажем, в «дружественный формат».

Допустимый / нормальный ввод может быть: '11: 30 'или' 1: 30 ' Моя проблема в том, что в моем устройстве установлен часовой пояс Нью-Йорк (-4 по Гринвичу) и даже жесткий код в этом примере! эта функция продолжает преобразовывать время в -5 GMT (6:30 AM и 8:30 PM соответственно)

-(NSString*) convertServerTimeToAppTimeFormat:(NSString*) input {
NSDateFormatter *dateFormatInput = [[NSDateFormatter alloc] init];
[dateFormatInput setDateFormat:@"HH:mm"];
[dateFormatInput setTimeZone :[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *date = [dateFormatInput dateFromString:input];

NSDateFormatter *dateFormatInputOutput = [[NSDateFormatter alloc] init];
[dateFormatInputOutput setDateFormat:@"h:mm a"];
[dateFormatInputOutput setTimeZone: [NSTimeZone localTimeZone]];
[dateFormatInputOutput setTimeZone:[NSTimeZone timeZoneWithName:@"America/New_York"]];
return  [dateFormatInputOutput stringFromDate:date];
}

Определенно должно быть что-то очень очевидное, чего я не вижу. Я бы обычно использовал:

[NSTimeZone localTimeZone]

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

Ответы [ 2 ]

2 голосов
/ 15 мая 2019

Проблема заключается в том, что от того, в каком штате Нью-Йорк на 4 или 5 часов отстает время по Гринвичу / UTC, зависит от того, используете ли вы в настоящее время летнее время или нет. В настоящее время у нас "летнее время", но при отсутствии информации об обратном форматер даты собирается принять дату 1 января 2000 года, которая не относится к летнему времени. Отсюда и отключение.

Но вы можете установить defaultDate форматера на сегодня:

NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]];
[dateFormatInput setDefaultDate:today];

Приведенный выше форматер будет иметь значение по умолчанию для сегодняшней даты. Очевидно, что если ваш ввод имеет отдельное поле, в котором указывается, какой день относится к этому времени, используйте его.

Но, установив defaultDate, это позволит строке только для времени узнать, следует ли применять переход на летнее время или нет, давая желаемое преобразование часового пояса.


Кстати, я бы предложил не использовать dateFormat для выходной строки. Укажите timeStyle, и он будет отформатирован в соответствии с настройками устройства пользователя:

NSDateFormatter *dateFormatInputOutput = [[NSDateFormatter alloc] init];
[dateFormatInputOutput setTimeStyle:NSDateFormatterShortStyle];
return [dateFormatInputOutput stringFromDate:date];

В частности, если пользователь настроил свое устройство на 24-часовые часы, вышеприведенное будет учитывать все, что указал пользователь, вместо принудительного использования формата, который может быть ему не по вкусу.

Также обратите внимание, что вам не нужно принудительно устанавливать часовой пояс или локаль (если вы действительно не намеревались принудительно переводить его в Нью-Йорк, даже если пользователь находится в CA), поскольку он также по умолчанию будет использовать настройки устройства пользователя. Это зависит только от того, действительно ли вы хотели перевести его в восточный часовой пояс или нет.


Если вы читаете строки даты / времени из веб-службы, вы также можете указать согласованный языковой стандарт в соответствии с Техническим примечанием 1480 . Технически, это строка времени, это может не понадобиться, но это хорошая практика:

[dateFormatInput setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
2 голосов
/ 15 мая 2019

Когда вы анализируете только время без даты, перенастроенная дата будет Jan 1, 2000.Из-за перехода на летнее время смещение между вами и временем по Гринвичу сегодня может отличаться от того, которое было бы 1 января. Вам нужно будет добавить несколько дополнительных шагов в середине кода, чтобы заставить его работать правильно.

Я действительно зациклен на Objective-C, поэтому я просто подытожу шаги, которые вам нужно сделать.Я мог бы также опубликовать решение в быстрой форме, так как вы думаете, что это поможет, поскольку он в основном один и тот же, только другой синтаксис.

  1. Сохраните ваш код, который создает date из строки
  2. Создайте Calendar с часовым поясом, установленным на GMT
  3. Создайте DateComponents, в котором указан год, месяц, день для текущей даты
  4. Создайте DateComponents счас, мин. от date
  5. Объедините два DateComponents вместе, отредактируйте один из них или создайте новый
  6. Используйте календарь, чтобы получить дату из компонентов
  7. Используйте ваш dateFormatInputOutput форматтер для создания строки с этой даты
...