Swift 5中DateFormatter与ISO8601DateFormatter解析差异及正确性问询
Swift 5中两种日期转换方式的差异分析
问题场景
现有日期字符串:
let dateString = "2019-11-09T08:14:09.361404Z"
分别用两种方式转换为Date:
方式一:使用DateFormatter
let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'" let date = dateFormatter.date(from: dateString) // 结果:2019-11-09 05:14:09 +0000
方式二:使用ISO8601DateFormatter
let dateFormatter = ISO8601DateFormatter() dateFormatter.formatOptions = [.withFractionalSeconds, .withInternetDateTime] let date = dateFormatter.date(from: dateString) // 结果:2019-11-09 08:14:09 +0000
两种结果相差3小时(与本地时区和GMT的差值一致),即使设置格式化器的时区为当前时区,结果差异依然存在。
差异原因
关键问题在于对日期字符串中Z的处理方式不同:
DateFormatter方式:你把Z用单引号'Z'包裹了,这会让DateFormatter将Z视为普通文本字符,完全忽略它的时区含义(Z代表UTC/Zulu时区)。此时DateFormatter会默认使用本地时区解析字符串中的时间部分(08:14:09),再将其转换为UTC时间输出。假设你的本地时区是UTC+3,那么本地时间08:14转成UTC就是05:14,这就是第一种结果的由来。ISO8601DateFormatter方式:这个类是专门为ISO8601格式设计的,它能正确识别Z作为UTC时区的标识,直接将字符串中的08:14:09.361404Z解析为UTC时间,所以得到的结果是正确的UTC时间点。
哪种结果正确?
第二种方式的结果是正确的。因为原日期字符串中的Z明确表示这是一个UTC时间,正确解析后得到的Date应该对应UTC的08:14:09。
如果要修正第一种方式,需要去掉Z的单引号,让DateFormatter识别其时区含义:
let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ" dateFormatter.timeZone = TimeZone(identifier: "UTC") // 可选,确保解析时用UTC时区 let date = dateFormatter.date(from: dateString) // 此时结果会和第二种方式一致:2019-11-09 08:14:09 +0000
内容的提问来源于stack exchange,提问作者Maxim
相关产品推荐
相关产品推荐

