解决ISO8601DateFormatter处理年初日期返回上一年的问题
新年首日ISO8601返回上一年份问题的解决方法
问题根源
该现象是ISO8601日历的周年(Week Year) 规则导致的正常结果:
ISO8601日历的year组件默认返回周年,判定规则为每年第一个包含周四的周为第1周,1978年1月1日为周日,属于1977年的最后一周,因此返回的周年为1977,和实际自然年不一致。
解决方法
无需修改日期、无需加偏移量,仅调整日历类型即可获取正确自然年:
改用格里高利(公历)日历获取日期组件,同时保证日历和日期解析器的时区完全一致,避免跨时区偏移。
修正后代码示例
import Foundation let datestring = "1978/1/1" var formatter = ISO8601DateFormatter() formatter.timeZone = TimeZone(abbreviation: "UTC") formatter.formatOptions = [.withFullDate] let date2 = formatter.date(from: datestring) ?? Date() print(date2) // 改用公历日历,时区和解析器保持一致 var calendar = Calendar(identifier: .gregorian) calendar.timeZone = formatter.timeZone! var year = calendar.component(.year, from: date2) var month = calendar.component(.month, from: date2) var day = calendar.component(.day, from: date2) var era = calendar.component(.era, from: date2) print("year \(year) month \(month) day \(day) era: \(era)") // 输出结果: // 1978-01-01 00:00:00 +0000 // year 1978 month 1 day 1 era: 1
注意事项
- 如果业务必须使用ISO8601日历体系,不要使用
.year组件,若需要对应自然年请仍通过公历日历获取,避免和周历规则冲突。 - 日期解析和组件读取的时区必须统一,否则零点日期容易出现跨天偏移,导致年份/月份/日期错误。
内容的提问来源于stack exchange,提问作者jonkimsr
相关产品推荐
相关产品推荐

