NSDateFormatter, я делаю что-то не так или это ошибка? - PullRequest
37 голосов
/ 27 сентября 2008

Я пытаюсь распечатать дату в определенном формате:

NSDate *today = [[NSDate alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyyMMddHHmmss"];
NSString *dateStr = [dateFormatter stringFromDate:today];

Если для iPhone установлено 24-часовое время, это работает нормально, если, с другой стороны, пользователь установил 24-часовое время, а затем обратно к AM / PM (работает нормально, пока вы не переключите этот параметр), затем добавляет AM / PM в конце, хотя я не просил об этом:

20080927030337 PM

Я что-то не так делаю или это ошибка в прошивке 2.1?

Редактировать 1: описание стало понятнее

Редактирование 2 обходного пути: оказывается, это ошибка, чтобы исправить ее, я установил символы AM и PM на "":

[dateFormatter setAMSymbol:@""];
[dateFormatter setPMSymbol:@""];

Ответы [ 8 ]

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

Причиной такого поведения является локаль, она устанавливает правильную локаль.

Установите для локального NSDateFormatter значение en_US_POSIX , чтобы исправить это. Работает как в 24-часовом, так и в 12-часовом формате.

On iPhone OS, the user can override the default AM/PM versus 24-hour time setting (via Settings > General > Date & Time > 24-Hour Time), which causes NSDateFormatter to rewrite the format string you set. С Apple Doc

Попробуйте это,

NSDate *today = [[NSDate alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
[dateFormatter setDateFormat:@"yyyyMMddHHmmss"];
NSString *dateStr = [dateFormatter stringFromDate:today];
14 голосов
/ 09 декабря 2009

Вот объяснение ошибки iPhone SDK (также есть в 3.1 beta SDK)

Сначала немного информации о пользовательском интерфейсе iPhone. Когда айфон пользователи меняют формат своего региона между, скажем, «США» и «Франция», настройка «24-часовое время» пользователя автоматически переключается к режиму, который является наиболее распространенным в этом регионе. Во Франции это установит 24-часовое время в положение «ON», а в США - «OFF». Пользователи могут затем вручную изменить этот параметр, и это где начинается беда.

Проблема в том, что NSDateFormatter «застревает» в 12 или 24-часовой режим времени, который пользователь выбрал вручную. Так что если Французский пользователь вручную выбирает 12-часовой режим и приложение запросил NSDateFormatter для вывода времени в 24-часовом формате «HHmm», он фактически получит время в 12-часовом формате, например «01:00 PM», как будто приложение вместо этого запросило «hhmm aa». Обратное произойдет, если пользователь из США выберет 24-часовой режим вручную: время вывода с 12-часовым форматом «хмммм аа» фактически получит вместо этого вы используете 24-часовой формат, например, «17:00".

Подробнее и возможном обходном пути можно найти в этом блоге .

12 голосов
/ 27 сентября 2008

Используя код, который вы разместили на симуляторе и телефоне с прошивкой 2.1 и отключенным 24-часовым временем, я никогда не добавлял AM / PM к dateStr, когда выполняю:

NSLog(@"%@", dateStr);

Делаете ли вы что-нибудь еще с dateStr, что вы не публикуете здесь? Как вы проверяете значение?

Последующее наблюдение

Попробуйте включить или выключить настройку am / pm. У меня не было проблемы, пока я не сделал это. Я печатаю так же, как и ты.

Хорошо, я вижу это, когда делаю это тоже. Это должно быть ошибка. Я рекомендую вам подать отчет об ошибке и просто проверить и отфильтровать ненужные символы.

9 голосов
/ 20 мая 2011

Установка локали в форматере даты на en_US устраняет проблему для меня:

    NSDateFormatter * f = [[NSDateFormatter alloc] init];
    [f setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
    f.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
    f.calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
    f.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease];

Я не уверен, что добавление календаря также необходимо, но это хорошо работает.

4 голосов
/ 17 июля 2010

Я думаю, что это решение.

NSDateFormatter *df =[[NSDateFormatter alloc] init];
        [df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
        NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];

[df setLocale: usLocale];

[usLocale release];

 NSDate *documento_en_Linea =[[[NSDate alloc] init]autorelease];

documento_en_Linea=[df dateFromString:@"2010-07-16 21:40:33"];

[df release];

        NSLog(@"fdocumentoenLineaUTC:%@!",documento_en_Linea);


//ouput  
     fdocumentoenLineaUTC:2010-07-16 09:40:33 p.m. -0500!
1 голос
/ 04 июля 2010

Для тех, кто находит этот вопрос, кто хочет использовать NSDateFormatter для анализа 24-часового времени и использует эту ошибку, используя NSDateComponents для анализа дат и времени, которые имеют известный формат, обходит эту проблему:

NSString *dateStr = @"2010-07-05";
NSString *timeStr = @"13:30";

NSDateComponents *components = [[NSDateComponents alloc] init];
components.year = [[dateStr substringToIndex:4] intValue];
components.month = [[dateStr substringWithRange:NSMakeRange(5, 2)] intValue];
components.day = [[dateStr substringFromIndex:8] intValue];
components.hour = [[timeStr substringToIndex:2] intValue];
components.minute = [[timeStr substringFromIndex:3] intValue];

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDate *date = [calendar dateFromComponents:components];

[components release];
[calendar release];
0 голосов
/ 21 июня 2012

Краткий ответ: попробуйте [dateFormatter setDateFormat:@"yyyyMMddhhmmss"]; для 12-часового формата (обратите внимание на нижний регистр hh).

Это была разочаровывающая тема, потому что многие веб-сайты указывают на использование HH в течение нескольких часов (включая официальную документацию Apple), но это устанавливает 24-часовой формат, тогда как hh использует 12-часовой формат. Подробнее см. http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns.

В качестве бонуса обратите внимание, что вы также можете использовать KK или kk для формата часа дня, который, вероятно, будет отключен на единицу.

Обновление: Недавно я смотрел на NSLocale (https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/Reference/Reference.html), и казалось бы, что вы можете использовать autoupdatingCurrentLocale, чтобы применить изменения, внесенные из приложения, в Locale. В результате, даже если телефон настроен на использование 24-часовых часов ( например, когда вы перешли во Францию), вы можете переключать приложение в режим 12/24, который не будет влиять на другие приложения на телефоне, или требовать выхода из приложения, чтобы внести изменения.

0 голосов
/ 12 сентября 2010

Это также должно работать (хотя я вижу некоторые странные результаты).

-(NSString*)lowLevTime:(NSString*)stringFormat {
    char buffer[50];
    const char *format = [stringFormat UTF8String];
    time_t rawtime;
    struct tm * timeinfo;
    time(&rawtime);
    timeinfo = localtime(&rawtime);
    strftime(buffer, sizeof(buffer), format, timeinfo);
    return [NSString  stringWithCString:buffer encoding:NSASCIIStringEncoding];
}
...