Здається, що у 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 заявила, що це "BAD" - 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
Баунті!
Я присуджую нагороду за найкращу (законну) пропозицію / критику, яку я бачу до середини дня вівторка. [Дивіться нижче - термін продовжений.]
Оновлення
Перегляньте пропозицію OMZ, ось що я знаходжу -
Ось версія категорії - файл h:
#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. Існує чітка різниця в двох результатах, і я вважаю, що версія категорії є неправильною. Зауважте, що журнал у версії категорії IS виконується (і зупинки, розміщені в коді, потрапляють), тому це не просто випадок, коли код якось не звикає.
Оновлення баунті:
Оскільки я ще не отримав жодної відповіді на відповідь, я продовжую граничний термін ще на два-два дні.
Баунті закінчується через 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 у категорії є щось "дивне".
Остаточна відповідь
Дивіться прийняту відповідь нижче.
- (NSDateFormatterBehavior)formatterBehavior
?