I\'m using a UIDatePicker to select a time. I am also customising the background of the picker, however I need 2 different images depending on whether the user is using 12 hour
and there's probably many, many more...
Even shorter than the others:
NSString *format = [NSDateFormatter dateFormatFromTemplate:@"j" options:0 locale:[NSLocale currentLocale]];
BOOL is24Hour = ([format rangeOfString:@"a"].location == NSNotFound);
The string formatting character to represent the am/pm symbol is "a", as documented in Unicode Locale Markup Language – Part 4: Dates.
The same document also explains the special template symbol "j":
This is a special-purpose symbol. It must not occur in pattern or skeleton data. Instead, it is reserved for use in skeletons passed to APIs doing flexible date pattern generation. In such a context, it 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).
The NSString
method dateFormatFromTemplate:options:locale:
is described in Apple's NSDateFormatter documentation:
Returns a localized date format string representing the given date format components arranged appropriately for the specified locale.
So, what that method will do is turn the @"j"
you pass in as a template in to a format string suitable for NSDateFormatter
. If this string contains the am / pm symbol @"a"
in it anywhere, then you know the locale (and other user settings being interrogated by the OS for you) wants am / pm to be displayed.
Swift (3.x) version of two most popular solutions in form of Date extension :
extension Date {
static var is24HoursFormat_1 : Bool {
let dateString = Date.localFormatter.string(from: Date())
if dateString.contains(Date.localFormatter.amSymbol) || dateString.contains(Date.localFormatter.pmSymbol) {
return false
}
return true
}
static var is24HoursFormat_2 : Bool {
let format = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.autoupdatingCurrent)
return !format!.contains("a")
}
private static let localFormatter : DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale.autoupdatingCurrent
formatter.timeStyle = .short
formatter.dateStyle = .none
return formatter
}()
}
Usage :
Date.is24HoursFormat_1
Date.is24HoursFormat_2
Swift (2.0) version of two most popular solutions in form of NSDate extension :
extension NSDate {
class var is24HoursFormat_1 : Bool {
let dateString = NSDate.localFormatter.stringFromDate(NSDate())
if dateString.containsString(NSDate.localFormatter.AMSymbol) || dateString.containsString(NSDate.localFormatter.PMSymbol) {
return false
}
return true
}
class var is24HoursFormat_2 : Bool {
let format = NSDateFormatter.dateFormatFromTemplate("j", options: 0, locale: NSLocale.autoupdatingCurrentLocale())
return !format!.containsString("a")
}
private static let localFormatter : NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.locale = NSLocale.autoupdatingCurrentLocale()
formatter.timeStyle = .ShortStyle
formatter.dateStyle = .NoStyle
return formatter
}()
}
Please note that Apple says following on NSDateFormatter (Date Formatters) :
Creating a date formatter is not a cheap operation. If you are likely to use a formatter frequently, it is typically more efficient to cache a single instance than to create and dispose of multiple instances. One approach is to use a static variable.
Thats the reason for static let
Secondly you should use NSLocale.autoupdatingCurrentLocale() ( for is24HoursFormat_1 ), that way you will always get the actual current state.