Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.dateInterval(of:for:) returns the wrong range for Gregorian eras #407

Open
davedelong opened this issue Feb 8, 2024 · 0 comments
Open
Assignees

Comments

@davedelong
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants