开发者

How can I determine if iPhone is set for 12 hour or 24 hour time display?

开发者 https://www.devze.com 2022-12-14 04:56 出处:网络
I thought I saw something answering this on SO recently but now I can\'t find it.Here is the code I am using now to determine if settings are for 24 hour time display.It works for me in the US, but I

I thought I saw something answering this on SO recently but now I can't find it. Here is the code I am using now to determine if settings are for 24 hour time display. It works for me in the US, but I don't know if it will work in all locales. Is this sufficient or is there a better way to find out the current setting for this?

+(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:0开发者_运维百科0" 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;
}


Here's the best way to do it:

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

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

in Swift:

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

Swift 4:

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

This uses a special date template string called "j". According to the ICU Spec, "j"...

requests the preferred hour format for the locale (h, H, K, or k), as determined by whether h, H, K, or k is used in the standard short time format for the locale. In the implementation of such an API, 'j' must be replaced by h, H, K, or k before beginning a match against availableFormats data. Note that use of 'j' in a skeleton passed to an API is the only way to have a skeleton request a locale's preferred time cycle type (12-hour or 24-hour).

That last sentence is important. It "is the only way to have a skeleton request a locale's preferred time cycle type". Since NSDateFormatter and NSCalendar are built on the ICU library, the same holds true here.


I've just asked a similar question on here and I've managed to figure out a decent way of determining this with a little function I've added to a category of NSLocale. It appears to be pretty accurate and haven't found any problems with it while testing with several regions.

@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!


I gave Dave's answer a shot, but when testing with German locale - a region where 24 hour time cycle is used - I realized it would be better to check for H or k in the format string instead of a, and that quoted substrings should be ignored.

For German locale I get back "HH a" when requesting the date format for template "j" in the iOS simulator, and "HH 'Uhr'" on the device. (Do not understand why there is a difference at all.)

Here is a category for NSLocale that I use to check for 24 hour time cycle:

@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


In Swift 4:

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


I my case I simply set timeStyle = .short for dateFormatter. (Swift)

let yourCustomDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
dateFormatter.amSymbol = "am"
dateFormatter.pmSymbol = "pm"
dateFormatter.timeStyle = .short
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let dateString = dateFormatter.string(from: yourCustomDate)

As result, dateString will be automatically converted to 12 or 24 time format. For example: 6:30 pm in 12-hours format and 18:30 in 24-hours format.

0

精彩评论

暂无评论...
验证码 换一张
取 消