Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSDateFormatter detect 24-hour clock in OS X and iOS

I would like to check if the user has selected the 12-hour or 24-hour clock as their preference in OS X and iOS. So I would like to detect if the user has done the following:

  • On the Mac, the System Preference is in Date & Time, Use a 24-hour Clock
  • On the iPhone, the Preference is in Settings, General, Date & Time, 24-Hour Time

I currently have the following code but it always returns the time as represented by the 12-hour clock, even if the system preference set by the user is for the 24-hour clock.

let timeFormatter = NSDateFormatter()
timeFormatter.locale = NSLocale.currentLocale()
timeFormatter.dateStyle = NSDateFormatterStyle.NoStyle
timeFormatter.timeStyle = NSDateFormatterStyle.ShortStyle

let ampmtext = timeFormatter.stringFromDate(NSDate())
println(ampmtext)

if ampmtext.rangeOfString("M") != nil {
    println("12-hour clock")
} else {
    println("24-hour clock")
}

I would like to find a solution written in Objective-C and Swift for both the Mac and iPhone that can detect if the device clock displays 24-hour or 12-hour time.

like image 937
wigging Avatar asked Jan 27 '15 03:01

wigging


People also ask

How do I display 24-Hour Time format?

Start Control Panel, and then under Clock, Language, and Region, click Change date, time or number formats. On the Formats tab, under Date and time formats, do one of the following: To change to 24-hour format, on the Short time drop-down list, select HH:mm and on the Long time drop-down list, select HH:mm:ss.

What is nsdateformatter?

Instances of NSDateFormatter create string representations of NSDate objects, and convert textual representations of dates and times into NSDate objects. For user-visible representations of dates and times, NSDateFormatter provides a variety of localized presets and configuration options.

How do I format a date in nsdate?

When you present information to the user, you should typically simply use the NSDateFormatter style constants to specify pre-defined sets of attributes that determine how a formatted date is displayed. If you need to generate a representation of a date in a precise format, however, you should use a format string.

How to display a quantity of time specified by nsdatecomponents object?

To represent a quantity of time specified by an NSDateComponents object, use NSDateComponentsFormatter instead. When displaying a date to a user, you set the dateStyle and timeStyle properties of the date formatter according to your particular needs.

What is the nsiso8601dateformatter class used for?

In macOS 10.12 and later or iOS 10 and later, use the NSISO8601DateFormatter class when working with ISO 8601 date representations. When working with fixed format dates, such as RFC 3339, you set the dateFormat property to specify a format string.


4 Answers

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.

like image 190
Matthias Bauch Avatar answered Oct 22 '22 00:10

Matthias Bauch


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
}
like image 21
Megagator Avatar answered Oct 21 '22 23:10

Megagator


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
}
like image 29
Sreekuttan Avatar answered Oct 21 '22 22:10

Sreekuttan


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.

like image 44
sbooth Avatar answered Oct 22 '22 00:10

sbooth