NSDateFormatter未按预期工作的原因及正确格式化方案咨询
关于DateFormatter时区与12小时制格式化的问题
先还原你遇到的异常场景:
let testDate = Date(timeIntervalSinceReferenceDate: 725840000.0) print(testDate) // 输出:2024-01-01 22:13:20 +0000 let fmt = DateFormatter() fmt.timeZone = TimeZone(abbreviation: "America/Los_Angeles") fmt.dateFormat = "h:mm a" print(fmt.string(from: testDate)) // 输出:14:13 // 指定的AM/PM标识为何缺失? fmt.dateFormat = "h:mm a z" print(fmt.string(from: testDate)) // 输出:14:13 PM PST // 14:13 PM的格式明显错误!
疑问解答
1. 为何AM/PM标识仅配合时区时才输出,单独使用时不显示?
这是因为你未设置DateFormatter的locale。默认情况下,DateFormatter会沿用系统当前区域设置,如果你的系统区域属于使用24小时制的地区(比如中国),即便指定了a格式符,也会被区域设置覆盖,不显示AM/PM。你看到的“配合时区才输出”其实是另一个冲突问题的表现,本质还是locale配置缺失导致的行为异常。
2. 为何会出现24小时制时间与AM/PM标识同时出现的情况?
核心原因依然是locale未正确配置。当你指定时区但未指定locale时,DateFormatter的行为会出现规则冲突:h本应对应12小时制小时数,但系统默认的24小时制区域设置会强制使用24小时格式,同时a标识又被保留,最终导致“14:13 PM”这种矛盾输出。
3. 如何得到预期的“2:13 PM”格式?文档与实现是否不匹配?
文档是正确的,问题出在你的DateFormatter配置不全。正确做法是同时设置locale为使用12小时制的固定区域(比如en_US_POSIX),确保格式符严格遵循你指定的规则。
修正后的代码:
let testDate = Date(timeIntervalSinceReferenceDate: 725840000.0) let fmt = DateFormatter() fmt.timeZone = TimeZone(identifier: "America/Los_Angeles") // 建议用identifier而非abbreviation,稳定性更高 fmt.locale = Locale(identifier: "en_US_POSIX") fmt.dateFormat = "h:mm a" print(fmt.string(from: testDate)) // 输出:2:13 PM
补充说明:en_US_POSIX是不受系统语言/区域偏好影响的固定区域设置,适合用于固定格式的日期时间解析或格式化,能保证格式规则的一致性。
内容的提问来源于stack exchange,提问作者executor21
相关产品推荐
相关产品推荐

