¿Cuál es la mejor manera de lidiar con la configuración regional de NSDateFormatter "feechur"?

Parece queNSDateFormatter tiene una "característica" que te muerde inesperadamente: si haces una operación de formato "fijo" simple como:

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

Entonces funciona bien en los EE. UU. Y en la mayoría de los lugares HASTA ... alguien con su teléfono configurado en una región de 24 horas establece el interruptor de 12/24 horas en la configuración a 12. Luego, lo anterior comienza a agregar "AM" o "PM" en el final de la cadena resultante.

(Ver, por ejemplo,NSDateFormatter, ¿estoy haciendo algo mal o es un error?)

(Y verhttps: //developer.apple.com/library/content/qa/qa1480/_index.htm)

parentemente, Apple ha declarado que esto es "MALO" - Roto según lo diseñado, y no lo van a arreglar.

Aparentemente, la elusión es establecer la configuración regional del formateador de fecha para una región específica, generalmente en los Estados Unidos, pero esto es un poco desordenado:

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

No está mal en onsies-twoosies, pero estoy tratando con unas diez aplicaciones diferentes, y la primera que miro tiene 43 instancias de este escenario.

Entonces, ¿alguna idea inteligente para una macro / clase anulada / lo que sea para minimizar el esfuerzo de cambiar todo, sin hacer que el código se oscurezca? (Mi primer instinto es anular NSDateFormatter con una versión que establezca la configuración regional en el método init. Requiere cambiar dos líneas: la línea alloc / init y la importación agregada).

Adiciona

Esto es lo que se me ocurrió hasta ahora: parece funcionar en todos los escenarios:

@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
¡Generosidad

Otorgaré la recompensa a la mejor (legítima) sugerencia / crítica que veo hasta el mediodía del martes. [Ver abajo - plazo extendido.]

Actualiza

ropuesta de @Re OMZ, esto es lo que estoy encontrando:

Aquí está la versión de categoría - archivo h:

#import <Foundation/Foundation.h>


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

Categoría archivo 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

El código

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];

El resultado

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)

El teléfono [hace que un iPod Touch] esté configurado en Gran Bretaña, con el interruptor 12/24 en 12. Hay una clara diferencia en los dos resultados, y considero que la versión de la categoría es incorrecta. Tenga en cuenta que el registro en la versión de categoría SE está ejecutando (y las paradas colocadas en el código se golpean), por lo que no se trata simplemente de que el código de alguna manera no se utilice.

ctualización @Bounty:

Desde que aún no he recibido ninguna respuesta aplicable, extenderé el plazo de recompensa por otro día o dos.

Bounty finaliza en 21 horas: irá a quien haga el mayor esfuerzo para ayudar, incluso si la respuesta no es realmente útil en mi caso.

Una observación curiosa

Modificó ligeramente la implementación de la categoría:

#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

Básicamente solo cambió el nombre de la variable de configuración regional estática (en caso de que haya algún conflicto con la estática declarada en la subclase) y agregó el NSLog adicional. Pero mira lo que imprime 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

Como puede ver, el setLocale simplemente no lo hizo. La configuración regional del formateador sigue siendo en_GB. Parece que hay algo "extraño" sobre un método init en una categoría.

Respuesta fina

Ver el respuesta aceptada abajo.

Respuestas a la pregunta(5)

Su respuesta a la pregunta