Duplicating 24-hour format issue in simulator

On a device, If I have a string, say "04:00 PM" and convert it to a date using a dateformatter:

let dateFormatter = DateFormatter() dateFormatter.format = "h:mm a"

let d = dateFormatter.date(from: "04:00 PM")

If the device is set to a 24 hour time format, then d is nil. On a simulator, the result is a date. What I want to do is to somehow set up the simulator to return a nil under this circumstance. How do I do that?

Things I have tried: setting 24-hour format on the Mac, setting the region on the Mac, setting the region on the simulator, setting the locale in the simulator (maybe there's a locale setting I missed). For the Mac update settings, I reset the simulator afterward for the change to take effect.

So far nothing I've tried works.

The purpose of this is to allow automated tests to be able to detect these nils that will happen on actual devices.

On a device, If I have a string, say "04:00 PM" and convert it to a date using a dateformatter:

let dateFormatter = DateFormatter() dateFormatter.format = "h:mm a"
let d = dateFormatter.date(from: "04:00 PM")

This code is incorrect. It’s not safe to use a fixed-format date formatter without also pinning the locale. See QA1480 NSDateFormatter and Internet Dates for a detailed explanation of this.

As to what you should do, that depends on your specific circumstances. Where does this time string come from?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I know it's wrong, and I've pointed it out to the development team who coded it.

That would have been a useful factoid to include in your question, eh?

There are at least two ways that this code can fail. The first is the most common one:

  1. On a real device, in Settings > General > Language & Region, configure your phone to use a 12-hour locale, like the US.

  2. In Settings > General > Date & Time, enable 24-hour time.

The second is explained in Parsing Dates Without Times.

Combined, the ‘win’ for using DateFormatter to parse fixed-format time-only strings is illusory. IMO you’re better off writing your own parser. Doing that obviates the need for a unit test because your parser is clearly independent of the user’s locale preferences.

If you want to go down the DateFormatter path regardless, I don’t think there’s a good way to configure the simulator to behave this way because:

  • The simulator does not support Settings > General > Date & Time [1].

  • In Xcode, Product > Scheme > Edit Scheme > {Run,Test} > App Region does not let you specify a 12-hour region with a 24-hour override [2].

You could probably hack around this by grovelling through user defaults to find the key that’s set by the 24-Hour Time switch. For an example of that process, see this thread.

IMPORTANT Relying on undocumented preferences keys for testing is OK, but do not encode that info into a shipping product.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] The fact that it doesn’t is kinda annoying IMO and, if you agree, feel free to file a bug about that. Please post your bug number, just for the record.

[2] Again, that’s fine bug fodder IMO.

Experienced the same thing, whenever I change the phone settings to a 24 hour format it spits out nil for some reason.

I tried changing the local to: dateFormatter.locale = Locale(identifier: "en_US_POSIX") and it worked

Duplicating 24-hour format issue in simulator
 
 
Q