Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
271 views
in Technique[技术] by (71.8m points)

ios - NSDateFormatter still parsing instead having incorrect format

Having some problems parsing date. I have an array of supported formats and once I receive the date (string) from API, I try to parse it iterating through the formats until I get a valid NSDate object.

A snippet from Xcode Playground --

let dateString = "02/06/1987" // --> want to parse into this Feb 6, not Jun 2
let dateFormatIncorrect = "dd.MM.yyyy"
let dateFormatCorrect = "MM/dd/yyyy"
let dateFormatter = NSDateFormatter()

dateFormatter.dateFormat = dateFormatIncorrect
let date = dateFormatter.dateFromString(dateString)! // "Jun 2, 1987, 12:00 AM"

dateFormatter.dateFormat = dateFormatCorrect
let date2 = dateFormatter.dateFromString(dateString)! // "Feb 6, 1987, 12:00 AM"

Why does it parse the date even though the format is clearly incorrect for a given string? Could not find anything in the docs regarding date formatter ignoring separators.

I realise the proper solution would be to have a fixed format returned from API but was wondering what is happening here?

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It seems that NSDateFormatter is extremely lenient when parsing a date string. Unfortunately, I could not find a reference for this, but even with

dateFormatIncorrect = "'aaa'dd'bbb'MM'ccc'yyyy'ddd'"

the date string "02/06/1987" is successfully parsed. There is a lenient property, but that is false by default, and setting it explicitly makes no difference.

As a workaround, you could convert the parsed date back to a string, and only if the result is equal to the original string, the date is accepted:

extension NSDateFormatter {

    func checkedDateFromString(string : String) -> NSDate? {
        if let date = self.dateFromString(string) {
            if self.stringFromDate(date) == string {
                return date
            }
        }
        return nil
    }
}

Using this custom extension,

dateFormatter.checkedDateFromString(dateString)

returns nil for the incorrect date format.


Generally, if you work with fixed date formats, you should also set the locale to "en_US_POSIX"

dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")

(see What is the best way to deal with the NSDateFormatter locale "feechur"?). However, this makes no difference for this particular problem.


Update for Swift 3:

extension DateFormatter {

    func checkedDate(from: String) -> Date? {
        if let date = date(from: from), string(from: date) == from {
            return date
        }
        return nil
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...