Попробуй это....

ся, чтоNSDateFormatter имеет «функцию», которая неожиданно кусает вас: если вы выполняете простую операцию «фиксированного» формата, такую ​​как:

NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
[fmt setDateFormat:@"yyyyMMddHHmmss"];
NSString* dateStr = [fmt stringFromDate:someDate];
[fmt release];

Тогда он отлично работает в США и большинстве регионов до тех пор, пока ... кто-то с его телефоном, настроенным на 24-часовой регион, устанавливает переключатель 12/24 часа в настройках на 12. Затем вышеприведенное начинает привязывать «AM» или «PM» к конец результирующей строки.

(См., Например,NSDateFormatter, я делаю что-то не так или это ошибка?)

(И увидетьhttps://developer.apple.com/library/content/qa/qa1480/_index.html)

Очевидно, Apple объявила, что это «ПЛОХО» - Broken As Designed, и они не собираются это исправить.

Обходное решение, по-видимому, заключается в установке языкового стандарта форматирования даты для определенного региона, как правило, США, но это немного грязно:

NSLocale *loc = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
[df setLocale: loc];
[loc release];

Не так уж и плохо в первый раз, но я имею дело примерно с десятью различными приложениями, и первое, на которое я смотрю, имеет 43 экземпляра этого сценария.

Итак, есть ли какие-нибудь умные идеи для макроса / переопределенного класса / чего бы то ни было, чтобы минимизировать усилия по изменению всего, не делая код неясным? (Мой первый инстинкт - переопределить NSDateFormatter версией, которая установит языковой стандарт в методе init. Требуется изменить две строки - строку alloc / init и добавленный импорт.)

добавленной

Это то, что я придумала до сих пор - кажется, работает во всех сценариях:

@implementation BNSDateFormatter

-(id)init {
static NSLocale* en_US_POSIX = nil;
NSDateFormatter* me = [super init];
if (en_US_POSIX == nil) {
    en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
[me setLocale:en_US_POSIX];
return me;
}

@end
Bounty!

Я награжу награду лучшим (законным) предложением / критикой, которое я вижу к полудню вторника. [См. Ниже - срок продлен.]

Обновить

Относительно предложения ОМЗ, вот что я нахожу -

Вот версия категории - h file:

#import <Foundation/Foundation.h>


@interface NSDateFormatter (Locale)
- (id)initWithSafeLocale;
@end

Файл категории m:

#import "NSDateFormatter+Locale.h"


@implementation NSDateFormatter (Locale)

- (id)initWithSafeLocale {
static NSLocale* en_US_POSIX = nil;
self = [super init];
if (en_US_POSIX == nil) {
    en_US_POSIX = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
NSLog(@"Category's locale: %@ %@", en_US_POSIX.description, [en_US_POSIX localeIdentifier]);
[self setLocale:en_US_POSIX];
return self;    
}

@end

Код:

NSDateFormatter* fmt;
NSString* dateString;
NSDate* date1;
NSDate* date2;
NSDate* date3;
NSDate* date4;

fmt = [[NSDateFormatter alloc] initWithSafeLocale];
[fmt setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
dateString = [fmt stringFromDate:[NSDate date]];
NSLog(@"dateString = %@", dateString);
date1 = [fmt dateFromString:@"2001-05-05 12:34:56"];
NSLog(@"date1 = %@", date1.description);
date2 = [fmt dateFromString:@"2001-05-05 22:34:56"];
NSLog(@"date2 = %@", date2.description);
date3 = [fmt dateFromString:@"2001-05-05 12:34:56PM"];  
NSLog(@"date3 = %@", date3.description);
date4 = [fmt dateFromString:@"2001-05-05 12:34:56 PM"]; 
NSLog(@"date4 = %@", date4.description);
[fmt release];

fmt = [[BNSDateFormatter alloc] init];
[fmt setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
dateString = [fmt stringFromDate:[NSDate date]];
NSLog(@"dateString = %@", dateString);
date1 = [fmt dateFromString:@"2001-05-05 12:34:56"];
NSLog(@"date1 = %@", date1.description);
date2 = [fmt dateFromString:@"2001-05-05 22:34:56"];
NSLog(@"date2 = %@", date2.description);
date3 = [fmt dateFromString:@"2001-05-05 12:34:56PM"];  
NSLog(@"date3 = %@", date3.description);
date4 = [fmt dateFromString:@"2001-05-05 12:34:56 PM"]; 
NSLog(@"date4 = %@", date4.description);
[fmt release];

Результат:

2011-07-11 17:44:43.243 DemoApp[160:307] Category's locale: <__NSCFLocale: 0x11a820> en_US_POSIX
2011-07-11 17:44:43.257 DemoApp[160:307] dateString = 2011-07-11 05:44:43 PM
2011-07-11 17:44:43.264 DemoApp[160:307] date1 = (null)
2011-07-11 17:44:43.272 DemoApp[160:307] date2 = (null)
2011-07-11 17:44:43.280 DemoApp[160:307] date3 = (null)
2011-07-11 17:44:43.298 DemoApp[160:307] date4 = 2001-05-05 05:34:56 PM +0000
2011-07-11 17:44:43.311 DemoApp[160:307] Extended class's locale: <__NSCFLocale: 0x11a820> en_US_POSIX
2011-07-11 17:44:43.336 DemoApp[160:307] dateString = 2011-07-11 17:44:43
2011-07-11 17:44:43.352 DemoApp[160:307] date1 = 2001-05-05 05:34:56 PM +0000
2011-07-11 17:44:43.369 DemoApp[160:307] date2 = 2001-05-06 03:34:56 AM +0000
2011-07-11 17:44:43.380 DemoApp[160:307] date3 = (null)
2011-07-11 17:44:43.392 DemoApp[160:307] date4 = (null)

На телефоне [сделайте так, чтобы iPod Touch] был установлен в Великобритании, с переключателем 12/24, установленным в 12. В двух результатах есть четкая разница, и я считаю версию категории неправильной. Обратите внимание, что журнал в версии категории исполняется (и удаляются остановки в коде), так что это не просто случай, когда код как-то не используется.

Обновление награды:

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

Баунти заканчивается через 21 час - она ​​отправится тому, кто приложит максимум усилий, чтобы помочь, даже если ответ не очень полезен в моем случае.

Любопытное наблюдение

Немного изменил реализацию категории:

#import "NSDateFormatter+Locale.h"

@implementation NSDateFormatter (Locale)

- (id)initWithSafeLocale {
static NSLocale* en_US_POSIX2 = nil;
self = [super init];
if (en_US_POSIX2 == nil) {
    en_US_POSIX2 = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
}
NSLog(@"Category's locale: %@ %@", en_US_POSIX2.description, [en_US_POSIX2 localeIdentifier]);
[self setLocale:en_US_POSIX2];
NSLog(@"Category's object: %@ and object's locale: %@ %@", self.description, self.locale.description, [self.locale localeIdentifier]);
return self;    
}

@end

По сути, просто изменили имя статической переменной локали (в случае, если был какой-то конфликт со статической переменной, объявленной в подклассе) и добавили дополнительный NSLog. Но посмотрите, что печатает NSLog:

2011-07-15 16:35:24.322 DemoApp[214:307] Category's locale: <__NSCFLocale: 0x160550> en_US_POSIX
2011-07-15 16:35:24.338 DemoApp[214:307] Category's object: <NSDateFormatter: 0x160d90> and object's locale: <__NSCFLocale: 0x12be70> en_GB
2011-07-15 16:35:24.345 DemoApp[214:307] dateString = 2011-07-15 04:35:24 PM
2011-07-15 16:35:24.370 DemoApp[214:307] date1 = (null)
2011-07-15 16:35:24.378 DemoApp[214:307] date2 = (null)
2011-07-15 16:35:24.390 DemoApp[214:307] date3 = (null)
2011-07-15 16:35:24.404 DemoApp[214:307] date4 = 2001-05-05 05:34:56 PM +0000

Как видите, setLocale просто нет. Язык форматирования по-прежнему en_GB. Похоже, что в методе init в категории есть что-то «странное».

Окончательный ответ

Увидетьпринятый ответ ниже.

Ответы на вопрос(5)

Ваш ответ на вопрос