使用Europe/Sofia时区时DateFormatter无法解析1995-03-26日期的原因
DateFormatter解析日期异常:Europe/Sofia时区下1995-03-26无法解析的原因
问题场景
使用DateFormatter解析后端返回的日期字符串时,发现当时区设置为"Europe/Sofia"时,无法从"1995-03-26"初始化日期;切换为固定GMT+2时区或其他日期(如1995-03-25、1995-03-27)则解析正常。测试代码如下:
import Foundation let serverLocalDateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy-MM-d" formatter.timeZone = TimeZone(secondsFromGMT: 60 * 60 * 2) return formatter }() let serverLocalDateFormatter2: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy-MM-d" formatter.timeZone = TimeZone(identifier: "Europe/Sofia") return formatter }() let testCase1 = "1995-03-26" let testCase2 = "1995-03-27" let testCase3 = "1995-03-25" serverLocalDateFormatter.date(from: testCase1) serverLocalDateFormatter2.date(from: testCase1) serverLocalDateFormatter.date(from: testCase2) serverLocalDateFormatter.date(from: testCase3)
异常原因
问题核心在于Europe/Sofia时区1995年的夏令时切换规则:
- 1995年3月26日是保加利亚夏令时启动的日期,当地时间在3月25日23:00结束后,直接跳转到3月26日01:00,跳过了26日00:00到00:59:59的整个时间段。
DateFormatter解析仅含日期的字符串时,会默认补充时间为00:00:00。由于这个时间点在Europe/Sofia时区中不存在,date(from:)方法无法生成有效的Date实例,因此返回nil。- 使用固定GMT+2时区的格式化器可以解析,是因为它不考虑时区的夏令时历史变更,直接将"1995-03-26"视为GMT+2时区的00:00,对应的UTC时间为1995-03-25 22:00:00,这是一个真实存在的有效时间点。
内容的提问来源于stack exchange,提问作者Roman Kovalchuk
相关产品推荐
相关产品推荐

