解析日期时遇到一些问题。我有一系列支持的格式,一旦我从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返回固定格式,但想知道这里发生了什么?
感谢。
答案 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的字符串适合输入字符串。