Open
Description
Below is a minimal reproduction case:
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(secondsFromGMT: 0)!
let eraComponents = DateComponents(era: 1)
let anyEraDate = calendar.date(from: eraComponents)!
calendar.component(.era, from: anyEraDate) == 1 // TRUE
print(anyEraDate.description) // 0001-01-01 00:00:00 +0000
let eraRange = calendar.dateInterval(of: .era, for: anyEraDate)!
calendar.component(.era, from: eraRange.start) == 1 // FALSE
print(eraRange.start.description) // -139365-04-28 21:34:56 +0000
print(eraRange.end.description) // 0001-01-03 00:00:00 +0000
The fundamental problem is that calendar.date(from: eraComponents)
is using a formula based on Julian days for converting it to a timestamp. DateComponents(era: 1)
becomes Julian Day 1721423
, which is right on the BC/AD boundary, as expected. That Date
has a timeIntervalSinceReferenceDate
of -63114076800.0
.
However, .dateInterval(of:for:)
checks for dates that are close to the era boundary, and returns a hard-coded boundary:
...
case .era:
if time < -63113904000.0 {
return DateInterval(start: Date(timeIntervalSinceReferenceDate: -63113904000.0 - inf_ti), duration: inf_ti)
} else {
...
That time interval of -63113904000.0
pegs the start of the era on 0001-01-03
, two days after the previously-returned Date
.
Metadata
Metadata
Assignees
Labels
No labels