repeatedTimePolicy parameter of Calendar.nextDate not working when matching nanoseconds?

Because of the transition from PDT to PST, there will be two 1:30 in 2/11/2025, which can be distinguished with the repeatedTimePolicy parameter when calling Calendar.nextDate.

var calendar = Calendar.init(identifier: .gregorian)
calendar.timeZone = TimeZone(identifier: "America/Los_Angeles")!

let d = calendar.date(from: .init(timeZone: calendar.timeZone, year: 2025, month: 11, day: 2, hour: 0, minute: 30))!

var components = DateComponents(hour: 1, minute: 30)

let date = calendar.nextDate(
    after: d,
    matching: components,
    matchingPolicy: .strict,
    repeatedTimePolicy: .last,
)
// 2025-11-02 09:30:00 +0000   (the second 1:30 in that day)

However, when we add nanosecond into the components to be matched, it is not able to find the second 1:30 and always return the first 1:30

var calendar = Calendar.init(identifier: .gregorian)
calendar.timeZone = TimeZone(identifier: "America/Los_Angeles")!

let d = calendar.date(from: .init(timeZone: calendar.timeZone, year: 2025, month: 11, day: 2, hour: 0, minute: 30))!

// include nanosecond
var components = DateComponents(hour: 1, minute: 30, nanosecond: 0)

let date = calendar.nextDate(
    after: d,
    matching: components,
    matchingPolicy: .strict,
    repeatedTimePolicy: .last,
)
// 2025-11-02 08:30:00 +0000 (the first 1:30 in that day)

Anyone know why is this happening?

It's a bug in the implementation: `Calendar.dates(byMatching: ...)` does not respect `repeatedTimePolicy` when `.nanosecond` is set · Issue #483 · swiftlang/swift-foundation · GitHub

1 Like