如何确定iPhone设置为12小时还是24小时时间显示?

问题描述 投票:0回答:6

我以为我最近在 SO 上看到了一些答案,但现在我找不到了。这是我现在用来确定设置是否用于 24 小时时间显示的代码。它在美国适用于我,但我不知道它是否适用于所有语言环境。这是否足够或者是否有更好的方法来找出当前设置?

+(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;
}
iphone datetime localization
6个回答
90
投票

这是最好的方法:

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

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

在斯威夫特:

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

斯威夫特 4:

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

这使用一个名为“j”的特殊日期模板字符串。根据 ICU 规范,“j”...

请求区域设置的首选小时格式(h、H、K 或 k),具体取决于区域设置的标准短时间格式中是否使用 h、H、K 或 k。在此类 API 的实现中,在开始与 availableFormats 数据进行匹配之前,必须将“j”替换为 h、H、K 或 k。请注意,在传递给 API 的框架中使用“j”是让框架请求区域设置的首选时间周期类型(12 小时或 24 小时)的唯一方法。

最后一句话很重要。它“是让骨架请求区域设置的首选时间周期类型的唯一方法”。由于

NSDateFormatter
NSCalendar
是基于 ICU 库构建的,因此这里也是如此。


22
投票

我刚刚在这里问了一个类似的问题,我已经设法找到了一个不错的方法来确定这个问题,我在

NSLocale
的类别中添加了一个小函数。它看起来相当准确,并且在多个地区进行测试时没有发现任何问题。

@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

希望这有帮助!


9
投票

我尝试了戴夫的答案,但在使用德国语言环境(使用 24 小时时间周期的地区)进行测试时,我意识到最好在格式字符串中检查 Hk 而不是 a ,并且引用的子字符串应该被忽略。

对于德语区域设置,当在 iOS 模拟器中请求模板“j”的日期格式时,我会返回“HH a”,在设备上请求“HH 'Uhr'”时。 (完全不明白为什么会有差异。)

这是

NSLocale
的类别,我用它来检查 24 小时时间周期:

@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
投票

在 Swift 4 中:

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

0
投票

自 iOS 16 和 macOS 13 起,您还可以查看当前区域设置的

hourCycle
值。这可能会避免一些潜在的问题,从 DateFormatter 中选择最佳的格式化代码来查询和测试:

if Locale.current.hourCycle == .oneToTwelve 
    || Locale.current.hourCycle == .zeroToEleven {

    // Do something for 12-hour
    ...
}

注意有 4 个不同的可能

.hourCycle
值。例如,午夜后一分钟可以用四种写法:0:01、0:01am、12:01am 和 24:01。

而且,根据 Apple 文档和快速测试(iOS 16.7.2),

.hourCycle
确实还考虑了用户可能设置的任何特定的 12/24 小时时间偏好。


-1
投票

就我而言,我只需为 dateFormatter 设置 timeStyle = .short 。 (斯威夫特)

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)

结果,dateString将自动转换为12或24时间格式。例如:12 小时制为下午 6:30,24 小时制为 18:30。

© www.soinside.com 2019 - 2024. All rights reserved.