DateFormatter为非常旧的日期提供奇怪的时区



对于我的一个客户,我正在处理非常旧的日期,例如:

  • 0572-06-17
  • 1000-06-17

当我将字符串转换为日期时,它有一个奇怪的时区。例子:

extension String {
func yearMonthDayDate() -> Date? {
return DateFormatter.yearMonthDayFormatter.date(from: self)
}
}
extension DateFormatter {
static let yearMonthDayFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = .current
dateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.locale = .current
return dateFormatter
}()
}
extension Date {
func zonedDate() -> String {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = .current
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXX"
dateFormatter.locale = .current
return dateFormatter.string(from: self)
}
}
print("1000-06-17".yearMonthDayDate()!.zonedDate())
1000-06-17T00:00:00+00:17

你可以看到时区是+00:17。为什么会出现这个奇怪的时区?

过去,各个地区通过观测日出日落的时间来保持自己的当地平均时间。这意味着每个城镇/城市的当地时间不是格林威治的一个漂亮的整数偏移,比如+17分钟。这并不是一个大问题,直到人们发明了有时刻表的火车。大约在19世纪,世界各国标准化了他们的当地时间,这就是为什么我们有很好的整数偏移,比如+1小时(大部分时间)。

所以在1000年,你们的时区,Europe/Brussels实际上比格林威治早17分钟,就我们所知道的历史而言。这段历史记录在IANAtz数据库中,这是TimeZone查询的。这就是为什么你得到了+00:17

有趣的是,当我问TimeZone距离格林尼治标准时间有多少秒时,它说0:

let date = Date(timeIntervalSinceNow: 86400 * 365 * -1000)
// this is 0
TimeZone(identifier: "Europe/Brussels")!.secondsFromGMT(for: date)

它可能将实际的秒数四舍五入。Java可以告诉你实际的答案:

// prints +00:17:30
System.out.println(ZoneId.of("Europe/Brussels")
.getRules().getOffset(LocalDate.of(1000, 1, 1).atStartOfDay()));