如何确定 iPhone 设置为 12 小时还是 24 小时时间显示?
Posted
技术标签:
【中文标题】如何确定 iPhone 设置为 12 小时还是 24 小时时间显示?【英文标题】:How can I determine if iPhone is set for 12 hour or 24 hour time display? 【发布时间】:2009-12-18 18:36:12 【问题描述】:我以为我最近在 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;
【问题讨论】:
【参考方案1】:这是最好的方法:
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 Spec,“j”...
请求区域设置的首选小时格式(h、H、K 或 k),由是否在区域设置的标准短时间格式中使用 h、H、K 或 k 来确定。在此类 API 的实现中,在开始与 availableFormats 数据进行匹配之前,必须将“j”替换为 h、H、K 或 k。请注意,在传递给 API 的框架中使用“j”是让框架请求区域设置的首选时间周期类型(12 小时或 24 小时)的唯一方法。
最后一句话很重要。它“是让骨架请求语言环境的首选时间周期类型的唯一方法”。由于NSDateFormatter
和NSCalendar
是在ICU 库上构建的,所以这里也是如此。
【讨论】:
不错的 3-liner。我想知道,“a”到底代表什么?是否有可能某些神秘的设置可以将时间周期符号更改为“AM”?范围行是否应该更改为`NSRange containsA = [formatStringForHours rangeOfString:@"a" options:NSCaseInsensitiveSearch];`? @Wienke "a" 是 AM/PM 指示符的 ICU 符号。它永远不可能是“A”,因为 ICU 使用“A”来表示完全不同的东西(一天中的毫秒数)。 +1,我觉得搜索一个具有定义的固定含义并且不会因语言环境而改变的字符更舒服。 我认为 sn-p 不会总是按预期工作。请参阅我对问题的回答:***.com/a/23586580/3617012 在阅读@iosX 评论后进一步查看了 ICU 规范 - 发现此段落“区域设置的 12 小时与 24 小时的偏好可以从时间数据中得出。如果小时符号是"h" 或 "K" 则格式为 12 小时;否则为 24 小时。可能是更安全的检查?【参考方案2】:我刚刚在此处询问了similar question,我已经设法通过添加到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
希望这会有所帮助!
【讨论】:
这个分类方法有个小问题。您应该在创建格式化程序之后添加一行[formatter setLocale:self];
,否则它仅使用当前语言环境。
没问题。顺便说一句,很好的解决方案,我很乐意使用它。
这行得通,但它的工作量比您需要完成的要多。【参考方案3】:
我试了一下 Dave 的回答,但是在使用德语区域进行测试时 - 使用 24 小时时间周期的区域 - 我意识到检查 H 或 k 在格式字符串中而不是 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
【讨论】:
感谢分享这个,在德国地区的 24 小时制时,它确实说“HH 'Uhr”。因此,我们建议某些语言可能会返回包含“a”的内容,即使是 24 小时格式,对吗?【参考方案4】:在 Swift 4 中:
let formatString: String = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)!
let hasAMPM = formatString.contains("a")
【讨论】:
【参考方案5】:在我的情况下,我只是将 timeStyle = .short 设置为 dateFormatter。 (斯威夫特)
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。
【讨论】:
这没有回答如何以编程方式确定设备设置的问题。这回答了如何以本地格式打印时间,这是一个不同的问题。以上是关于如何确定 iPhone 设置为 12 小时还是 24 小时时间显示?的主要内容,如果未能解决你的问题,请参考以下文章