NSDateFormatter仍在解析而不是格式不正确

时间:2014-11-10 09:29:35

标签: ios swift nsdateformatter

解析日期时遇到一些问题。我有一系列支持的格式,一旦我从API收到日期(字符串),我尝试解析它迭代格式,直到我得到一个有效的NSDate对象。

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"

为什么它会解析日期,即使格式对于给定字符串明显不正确?无法在文档中找到有关日期格式化程序忽略分隔符的任何内容。

我意识到正确的解决方案是从API返回固定格式,但想知道这里发生了什么?

感谢。

3 个答案:

答案 0 :(得分:4)

解析日期字符串时,似乎NSDateFormatter非常宽松。 不幸的是,我找不到这方面的参考,但即使是

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

成功解析日期字符串“02/06/1987”。有一个lenient属性, 但默认情况下为false,并明确设置它没有任何区别。

作为解决方法,您可以将已解析的日期转换回字符串,并且仅当 结果等于原始字符串,接受日期:

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)

返回nil以查找错误的日期格式。


通常,如果使用固定日期格式,则还应设置区域设置 到“en_US_POSIX”

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

(见What is the best way to deal with the NSDateFormatter locale "feechur"?)。但是,这对此没有任何影响 特别的问题。


Swift 3的更新:

extension DateFormatter {

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

答案 1 :(得分:1)

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

  

虽然原则上格式字符串指定了固定格式,但是   默认NSDateFormatter仍然采用用户的首选项(包括   考虑区域设置)

因此,您的偏好中定义的区域设置可能会使用' /'对于分隔符并满足“不正确的格式”#39;即使情况并非如此,苹果在几个地方也指出,NSDateFormatter可能并不一致。因此,请尝试设置如下所示的固定语言环境,看看是否有帮助

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

有关详细信息,请参阅以下链接:apple tech note。请注意与分隔符直接相关,但这可能是相关的。

答案 2 :(得分:0)

有一个类似的问题:

NSDateFormatter returns date object from invalid input

向Apple提交了一份错误报告。 结果:不会修复,因为更改可能会破坏工作代码,此外它更容错,从而提供某种便利。

  

请注意我们的工程团队已确定此问题   根据所提供的信息行事。

     

似乎ICU的udat_parseCalendar()非常宽容且仍然如此   即使字符串与格式不完全匹配,也能够解析。   我们理解在这些情况下格式化程序更喜欢返回nil   但是(1)我们没有简单的方法知道输入字符串   与ICU允许的格式不匹配,并且不会抛出   错误和(2)在这些情况下突然返回零几乎   肯定是个比较问题。

在我的情况下,我可以选择修改单元测试,并且在输入无效的情况下更加宽容,或者进行额外的检查(基于推荐的方法,这是该帖子的可接受答案)是否产生了NSDate的字符串适合输入字符串。