2009-12-18 17 views
37

Creí haber visto algo que respondía a esto recientemente, pero ahora no puedo encontrarlo. Aquí está el código que estoy usando ahora para determinar si la configuración es para mostrar la hora de 24 horas. Funciona para mí en los EE. UU., Pero no sé si funcionará en todos los entornos. ¿Es suficiente o hay una mejor manera de averiguar la configuración actual para esto?¿Cómo puedo determinar si el iPhone está configurado para visualización de 12 horas o 24 horas?

+(BOOL) use24HourClock 
{ 
    BOOL using24HourClock = NO; 

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];  
    [dateFormatter setLocale: [NSLocale currentLocale]];  
    [dateFormatter setDateStyle:kCFDateFormatterNoStyle]; 
    [dateFormatter setTimeStyle:kCFDateFormatterShortStyle];  
    // get date/time (1Jan2001 0000UTC) 
    NSDate* midnight = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:0]; 
    NSString* dateString = [dateFormatter stringFromDate: midnight]; 
    // dateString will either be "15:00" or "16:00" (depending on DST) or 
    // it will be "4:00 PM" or "3:00 PM" (depending on DST) 
    using24HourClock = ([dateString length] == 5); 
    [midnight release]; 
    [dateFormatter release];  

    return using24HourClock; 
} 

Respuesta

77

Esta es la mejor manera de hacerlo:

NSString *formatStringForHours = [NSDateFormatter dateFormatFromTemplate:@"j" options:0 locale:[NSLocale currentLocale]]; 

NSRange containsA = [formatStringForHours rangeOfString:@"a"]; 
BOOL hasAMPM = containsA.location != NSNotFound; 

en Swift:

let formatString: NSString = NSDateFormatter.dateFormatFromTemplate("j", options: 0, locale: NSLocale.currentLocale())! 
let hasAMPM = formatString.containsString("a") 

Este utiliza una cadena de plantilla de la fecha especial llamado "j". De acuerdo con la ICU Spec, "j" ...

peticiones el formato de hora preferida para la configuración regional (h, H, K, o k), como se determina por si h, H, se utiliza K, o k en el formato estándar de corto tiempo para la configuración regional. En la implementación de dicha API, 'j' debe reemplazarse por h, H, K o k antes de comenzar una coincidencia con los datos de los formatos disponibles. Tenga en cuenta que el uso de 'j' en un esqueleto pasado a una API es la única forma de que un esqueleto solicite el tipo de ciclo de tiempo preferido de una localidad (12 horas o 24 horas).

Esa última oración es importante. Es "la única forma de que un esqueleto solicite el tipo de ciclo de tiempo preferido de una localidad". Dado que NSDateFormatter y NSCalendar se crean en la biblioteca de la ICU, lo mismo se aplica aquí.

+0

Bonito 3-liner. Me pregunto, ¿qué significa exactamente la "a"?¿Es posible que algún ajuste oculto pueda cambiar el símbolo del ciclo de tiempo a "AM"? ¿Debería cambiarse la línea de rango a ' NSRange containsA = [formatStringForHours rangeOfString: @" a "options: NSCaseInsensitiveSearch];'? – Wienke

+3

@Wienke "a" es el símbolo de la ICU para el designador AM/PM. Nunca puede ser "A", porque la UCI usa "A" para significar algo totalmente diferente (milisegundos en el día). –

+0

+1, me siento mucho más cómodo buscando un personaje que tenga un significado fijo definido y que no cambie según la configuración regional. – DarkDust

21

he acaba de pedir un similar question de aquí y he conseguido encontrar una manera decente de determinar esto con una pequeña función que he añadido a una categoría de NSLocale. Parece ser bastante preciso y no ha encontrado ningún problema al probarlo en varias regiones.

@implementation NSLocale (Misc) 
- (BOOL)timeIs24HourFormat { 
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
    [formatter setLocale:self]; 
    [formatter setDateStyle:NSDateFormatterNoStyle]; 
    [formatter setTimeStyle:NSDateFormatterShortStyle]; 
    NSString *dateString = [formatter stringFromDate:[NSDate date]]; 
    NSRange amRange = [dateString rangeOfString:[formatter AMSymbol]]; 
    NSRange pmRange = [dateString rangeOfString:[formatter PMSymbol]]; 
    BOOL is24Hour = (amRange.location == NSNotFound && pmRange.location == NSNotFound); 
    [formatter release]; 
    return is24Hour; 
} 
@end 

Hope this helps!

+0

Hay un pequeño problema con este método de categoría. Debería agregar una línea '[formateador setLocale: self];' justo después de la creación del formateador; de lo contrario, ** solo ** usa la configuración regional actual. –

+0

¡Oh, sí, buen lugar! –

+0

No hay problema. Por cierto, gran solución, estoy feliz de usarlo. –

6

me dio la respuesta de Dave un tiro, pero cuando se prueba con configuración regional alemana - una región donde se utiliza ciclo de tiempo de 24 horas - me di cuenta de que sería mejor para comprobar si hay H o k en la cadena de formato en lugar de a, y las subcadenas citadas deben ignorarse.

Para la configuración regional alemana, obtengo "HH a" cuando solicito el formato de fecha para la plantilla "j" en el simulador de iOS, y "HH 'Uhr'" en el dispositivo. (No entiendo por qué hay una diferencia en absoluto.)

Aquí es una categoría para NSLocale que utilizo para comprobar si hay ciclo de tiempo de 24 horas:

@interface NSLocale (TwentyFourHourTimeCycleCheck) 

- (BOOL)uses24HourTimeCycle; 

@end 

@implementation NSLocale (TwentyFourHourTimeCycleCheck) 

- (BOOL)uses24HourTimeCycle 
{ 
    BOOL uses24HourTimeCycle = NO; 

    NSString *formatStringForHours = [NSDateFormatter dateFormatFromTemplate:@"j" options:0 locale:self]; 
    NSScanner *symbolScanner = [NSScanner scannerWithString:formatStringForHours]; 

    NSString *singleQuoteCharacterString = @"'"; 

    // look for single quote characters, ignore those and the enclosed strings 
    while (![symbolScanner isAtEnd]) { 

     NSString *scannedString = @""; 
     [symbolScanner scanUpToString:singleQuoteCharacterString intoString:&scannedString]; 

     // if 'H' or 'k' is found the locale uses 24 hour time cycle, and we can stop scanning 
     if ([scannedString rangeOfString:@"H"].location != NSNotFound || 
      [scannedString rangeOfString:@"k"].location != NSNotFound) { 

      uses24HourTimeCycle = YES; 

      break; 
     } 

     // skip the single quote 
     [symbolScanner scanString:singleQuoteCharacterString intoString:NULL]; 
     // skip everything up to and including the next single quote 
     [symbolScanner scanUpToString:singleQuoteCharacterString intoString:NULL]; 
     [symbolScanner scanString:singleQuoteCharacterString intoString:NULL]; 
    } 

    return uses24HourTimeCycle; 
} 

@end 
+0

Gracias por compartir esto, de hecho dice "HH 'Uhr" cuando está en el reloj de 24 horas en alemán. Entonces con esto estamos sugiriendo una posibilidad de que algún lenguaje pueda devolver algo que contenga "a" incluso en el formato de 24 horas ¿verdad? –

0

En Swift 4:

let formatString: String = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)! 
let hasAMPM = formatString.contains("a") 
Cuestiones relacionadas