NSDateFormatter detect 24-hour clock in OS X and iOS
The date template function has a neat trick. There is a template specifier j
which will turn into an hour format depending if the locale uses 12 or 24 hour format. It'll turn into something like h a
for 12 hour (en_US in this case) or HH
for 24 hour format (en_GB).
Then you just have to check if the date format contains a
//let locale = NSLocale(localeIdentifier: "de_DE")
//let locale = NSLocale(localeIdentifier: "en_US")
//let locale = NSLocale(localeIdentifier: "en_GB")
let locale = NSLocale.currentLocale()
let dateFormat = NSDateFormatter.dateFormatFromTemplate("j", options: 0, locale: locale)!
if dateFormat.rangeOfString("a") != nil {
println("12 hour")
}
else {
println("24 hour")
}
This should take format overwrites into account as well.
This is similar to your check, but you should not try to check for AM
or PM
. These are the english versions, there are many more. For example in Germany if you force a 12 hour format iOS uses nachm.
and vorm.
. The correct way is to check the format for a
.
The date format used in the menu bar on Mac OS X is contained in the file ~/Library/Preferences/com.apple.menuextra.clock.plist
. On my system (en_US locale) it looks like this for non-24 hour time:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>DateFormat</key>
<string>EEE h:mm a</string>
<key>FlashDateSeparators</key>
<false/>
<key>IsAnalog</key>
<false/>
</dict>
</plist>
and like this for 24-hour time:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>DateFormat</key>
<string>EEE H:mm</string>
<key>FlashDateSeparators</key>
<false/>
<key>IsAnalog</key>
<false/>
</dict>
</plist>
You can retrieve the format string using defaults read com.apple.menuextra.clock DateFormat
from the command line or NSUserDefaults
from Obj-C or Swift. You can then check if the format string contains a
. If it does the clock is not set to 24-hour time.
Use this extension
extension Locale {
static var is24Hour: Bool {
let dateFormat = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)!
return dateFormat.firstIndex(of: "a") == nil
}
}
Free to use anywhere
if Locale.is24Hour {
// Show 24 hour time
} else {
// Show 12 hour time
}
Swift 4
Here's a swift 4 interpretation of the accepted answer:
func is24Hour() -> Bool {
let dateFormat = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)!
return dateFormat.firstIndex(of: "a") == nil
}
Usage:
if is24Hour() {
// should show 24 hour time
} else {
// should show 12 hour time
}