NSDateFormatter - не учитывает настройки системы 12/24 часа (am / pm) в некоторых случаях - PullRequest
16 голосов
/ 29 мая 2011

Я хочу вывести дату (которая имеет относительные даты, например, сегодня, вчера и т. Д.) И время (в соответствии с настройкой 12/24 часов на устройстве iOS) Например,

  • Сегодня 17:48 (в 12-часовом режиме); и
  • Сегодня 17: 48 (в 24-часовом режиме)

Конфигурирование NSFormatter следующим образом (и использование stringFromDate :) не работает:

NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale: [NSLocale autoupdatingCurrentLocale]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];  // doesn't respect am/pm setting on iOS device (grrr!)
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDoesRelativeDateFormatting:YES]; // but does get relative dates

Здесь указываются относительные даты, но по умолчанию используется настройка 12/24 для локали, например, 12 часов для США и 24 часа для Великобритании. (Почему Apple думает, что британцы любят 24-часовые часы, я не знаю ...)

Обходной путь, который я принял, использует два NSDateFormatters, один для даты и один для времени. Похоже, что когда вы конфигурируете NSDateFormatter с dateStyle NSDateFormatterNoStyle и timeStyle NSDateFormatterShortStyle, тогда он учитывает настройку 12/24 часа. (Так что это просто, когда у вас ОБА установлены даты и время, что проблема.)

Я включил мою работу ниже на тот случай, если у кого-то еще возникнет аналогичная проблема. Есть ли более простой способ сделать это? Работа вокруг кажется несколько неловкой, и неясно, насколько уверенным я должен быть, он продолжит работать в будущих версиях iOS.

Работа вокруг

- (NSString*) humanRelativeDateAndTimeAlt: (NSDate*) date;
{

NSDateFormatter* relativeDateFormatter = [[NSDateFormatter alloc] init];
[relativeDateFormatter setLocale: [NSLocale autoupdatingCurrentLocale]];
[relativeDateFormatter setTimeStyle:NSDateFormatterNoStyle]; // no time for this formatter
[relativeDateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDoesRelativeDateFormatting:YES]; // relative dates

NSString* datePart = [[self relativeDateFormatter] stringFromDate:date];

NSDateFormatter* timeDateFormatter = [[NSDateFormatter alloc] init];
[timeDateFormatter setLocale:[NSLocale autoupdatingCurrentLocale]];
[timeDateFormatter setDateStyle: NSDateFormatterNoStyle]; // no date for this formatter
[timeDateFormatter setTimeStyle: NSDateFormatterShortStyle]; // does respect 12/24 hour setting

NSString* timePart = [timeDateFormatter stringFromDate:date];

int skipZero = 0;  // extra code to remove leading zero if present 
if ([[timePart substringToIndex:1] isEqualToString:@"0"]) skipZero = 1;

[relativeDateFormater release];
[timeDateFormatter release];

return [NSString stringWithFormat:@"%@ %@", datePart, [timePart substringFromIndex:skipZero]];
}

Ответы [ 5 ]

11 голосов
/ 08 ноября 2013

Причиной такого поведения является Locale, установите правильный Locale, установите local of your NSDateFormatter в en_US_POSIX , чтобы исправить это. Работает как в 24-часовом, так и в 12-часовом формате.

С Apple Doc :

В iPhone OS пользователь может переопределить настройку AM / PM по умолчанию вместо 24-часовой настройки времени (через «Настройки»> «Основные»> «Дата и время»> «24-часовое время»), в результате чего NSDateFormatter переписывает заданную вами строку формата.

Ссылка: Как лучше всего работать с «функцией» локали NSDateFormatter?

4 голосов
/ 14 июля 2011

Я столкнулся с той же проблемой. Я поднял это как ошибку с Apple, и разместил это на Open Radar:

http://openradar.appspot.com/9774877

3 голосов
/ 28 февраля 2014

Я нашел это решение:

 NSDate *now = [[NSDate alloc] init];
 NSTimeZone *localTimeZone = [NSTimeZone systemTimeZone];
 NSDateFormatter *rfc3339DateFormatter = [[NSDateFormatter alloc] init];
 NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];

 [rfc3339DateFormatter setLocale:enUSPOSIXLocale];
 [rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
 [rfc3339DateFormatter setTimeZone:localTimeZone];

 NSString *dateString = [rfc3339DateFormatter stringFromDate:now];

 NSLog(@"RFC 3339 datetime: %@", dateString);
 // 2013-06-27T10:27:08-0600
 // 2013-07-22T15:09:30+0100

Это решило 2 моих проблемы:

  1. Когда для пользователя установлен режим отображения 12 ч, вывод с этим форматером отображается как 24 ч.
  2. Когда вы вручную устанавливаете часовой пояс Дублина, на выходе не отображается dateTime с Z, но + 0000
1 голос
/ 14 мая 2017

Используйте этот формат

NSDateFormatter* relativeDateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"yyyy-MM-dd hh:mm a";

NSString *stringDate = [dateFormatter stringFromDate:[NSDate date]];
  1. Instad ЧЧ (час в день (0-23)) использование чч (час в час / час (1-12) )
  2. Добавьте a (маркер Am / pm) в конце формата.

Например: [NSDate date] равен 2017-05-14 12: 40: 00

  • В 24-часовое время вы получите 2017-05-14 12: 40
  • В 12 часов вы получите 2017-05-14 12:40

Для Сегодня | Вчера Я использую NSDateComponents для вычисления и возврата правильной даты.

NSCalendarUnit units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute;
NSDateComponents *components = [[NSCalendar currentCalendar] components:units fromDate:yourDate toDate:[NSDate date] options:0];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

if (components.year > 0) {
    dateFormatter.dateFormat = [NSString stringWithFormat:@"'%@' '%@' MMM d, YYYY", [@"last seen" localized], [@"at" localized]];
}
else if (components.day > 7) {
    dateFormatter.dateFormat = [NSString stringWithFormat:@"'%@' MMM d '%@' hh:mm a", [@"last seen" localized], [@"at" localized]];
}

NSString *relativeDateString = [dateFormatter stringFromDate: yourDate];
1 голос
/ 16 апреля 2013

У меня была похожая проблема, в результате чего я изменил dateFormat, а не указывал timeStyle.

    NSDateFormatter *formatter = [[ NSDateFormatter alloc ] init];

    if (self.datePickerMode == UIDatePickerModeDateAndTime){
        [formatter setDateFormat:[NSString stringWithFormat:@"%@ %@", f.dateFormat, @"HH:mm:ss"]];
    }

У меня хорошо получилось, надеюсь, это поможет.

...