Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSDateFormatter returns nil in swift and iOS SDK 8.0

Tags:

ios

I am reading the tutorial provided by Raywenderlich, Chapter 29 What’s New with Testing, and run into a strange problem.

Following is the code in the tutorial converting a string into date:

// Convert date string to date.
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"
var date: NSDate? = dateFormatter.dateFromString(dateString)

The dateString is of the form

2014-06-21 14:56:00 EST

However, the date variable is always nil.

NOTE: when playing this code in the playground, it works properly, as the image shows:

enter image description here

I am working in iOS SDK 8.0. Is it a bug of the SDK?


Updated

I am testing using a latest iPod Touch with iOS 8.

like image 355
HanXu Avatar asked Oct 02 '14 01:10

HanXu


2 Answers

When you set a dateFormat string you must also set the locale property to something that is compatible with the format provided. Otherwise the locale will be based on the device settings which may not be compatible.

The date format you provided here will work with the "en" locale but it will not work with many others, such as "eu". Here's an example:

let dateString = "2014-06-21 14:56:00 EST"

let localeStr = "eu" // this will give nil
let localeStr = "us" // this will succeed

let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: localeStr)
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"
var date: NSDate? = dateFormatter.dateFromString(dateString)

The problem here is "EST" which only exists in the north america. In all other locales it is an invalid timezone. If you change your date string to this:

"2014-06-21 14:56:00 UTC-5"

Then it the date will correctly format no matter what value locale is set to.

like image 113
Abhi Beckert Avatar answered Nov 03 '22 22:11

Abhi Beckert


NSDateFormatter's behaviors are heavily depends on it's locale. By default, it uses device locale. If you want consistent result from it, You should manually specify the locale. In most cases, en_US_POSIX is the best.

The document says:

If you're working with fixed-format dates, you should first set the locale of the date formatter to something appropriate for your fixed format. In most cases the best locale to choose is en_US_POSIX, a locale that's specifically designed to yield US English results regardless of both user and system preferences. en_US_POSIX is also invariant in time (if the US, at some point in the future, changes the way it formats dates, en_US will change to reflect the new behavior, but en_US_POSIX will not), and between platforms (en_US_POSIX works the same on iPhone OS as it does on OS X, and as it does on other platforms).

Like this:

let dateString = "2014-06-21 14:56:00 EST"

let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss zzz"
var date: NSDate? = dateFormatter.dateFromString(dateString)
like image 39
rintaro Avatar answered Nov 04 '22 00:11

rintaro