NSDateFormatter仍然parsing,而不是格式不正确

有一些问题parsingdate。 我有一个支持的格式数组,一旦我从API接收date(string),我尝试parsing它遍历格式,直到我得到一个有效的NSDate对象。

Xcode游乐场的片段 –

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" 

为什么它parsingdate,即使格式显然不正确的给定的string? 无法find关于date格式化程序忽略分隔符的文档中的任何内容。

我知道正确的解决scheme是从API返回一个固定的格式,但想知道这里发生了什么?

谢谢。

看来NSDateFormatterparsingdatestring时非常宽松。 不幸的是,我找不到这个参考,但即使是

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

datestring“02/06/1987”被成功parsing。 有一个lenient财产,但这是默认false ,明确设置没有任何区别。

作为一种解决方法 ,您可以将parsing的date转换回string,并且只有当结果等于原始string时,date才被接受:

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

使用这个自定义扩展,

 dateFormatter.checkedDateFromString(dateString) 

对不正确的date格式返回nil


通常,如果您使用固定的date格式,则还应将语言环境设置为“en_US_POSIX”

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

(请参阅处理NSDateFormatter语言环境“feechur”的最佳方法是什么? )。 但是,这对于这个特殊的问题并没有什么不同。


Swift 3的更新:

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

这可能与NSDateFormatter在使用固定格式时无论如何将尊重用户设置有关

尽pipe原则上格式string指定了固定格式,但默认情况下,NSDateFormatter仍将用户的首选项(包括语言环境设置)考虑在内

所以可能是你的偏好定义的语言环境使用“/”作为分隔符,并满足“不正确的格式”。 即使情况并非如此,苹果在几个地方指出,NSDateFormatter可能并不一致。 所以请尝试设置一个固定的语言环境,看看是否有帮助

 NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; [dateFormatter setLocale:locale]; 

请看这些链接的细节: 苹果技术笔记 。 注意与分隔符直接相关,但可能是相关的。

有一个类似的问题:

NSDateFormatter从无效input中返回date对象

在苹果提交了一个错误报告。 结果:不会被修改,因为更改会破坏工作代码,另外它更容错,从而提供某种方便。

请知道,我们的工程团队已经根据所提供的信息确定了此问题的行为。

看来,ICU的udat_parseCalendar()是非常宽松的,即使string不完全匹配格式,仍然可以parsing。 我们理解,在这些情况下,格式化程序返回nil,但是(1)没有简单的方法让我们知道inputstring与ICU允许的格式不匹配,并且不会抛出错误;(2)突然返回在这些情况下,几乎可以肯定是一个bincompat问题。

在我的情况下,我可以select修改unit testing,并在input无效的情况下更宽容,或者进行额外的检查(基于推荐的方法,这是接受的答案)是否由此产生的NSDate的string适合inputstring。