Why does `ordinality(of: .day, in: .era, for: date)` give the same result for 2 dates in different time zones?

Consider the following code:

import UIKit

let date = Date()

guard let nycTimeZone = TimeZone(abbreviation: "EST"),
  let nzTimeZone = TimeZone(abbreviation: "NZDT") else {
    fatalError()
}
var nycCalendar = Calendar(identifier: .gregorian)
nycCalendar.timeZone = nycTimeZone
var nzCalendar = Calendar(identifier: .gregorian)
nzCalendar.timeZone = nzTimeZone

let now = Date()

let nycDayOfEra = nycCalendar.ordinality(of: .day, in: .era, for: now)
let nycDayOfYear = nycCalendar.ordinality(of: .day, in: .year, for: now)

var nzDayOfEra = nzCalendar.ordinality(of: .day, in: .era, for: now)
var nzDayOfYear = nzCalendar.ordinality(of: .day, in: .year, for: now)

As I write this, NYC time and Aukland NZ time give different days. That’s the case I’m interested in.

  • AdMob 7.3.1 and Swift 2.0 - Module not found
  • How to create a sidebar similar to the facebook app for iOS?
  • How to compare two strings ignoring case in Swift language?
  • Get name of AirPlay device using AVPlayer
  • Terminating app: Could not load NIB in bundle: 'NSBundle …' with name '7bK-jq-Zjz-view-r7i-6Z-zg0'
  • Animation of CGAffineTransform in iOS8 looks different than in iOS7
  • With the code above, the results for nycDayOfYear and nzDayOfYear are different (as of this writing I get nycDayOfYear=42 and nzDayOfYear=43.)

    That is as expected, and as desired. (I was working to answer a “how do I calculate the number of days of difference in two Dates evaluated in different time zones?” question.)

    However, it would take a bunch of messy adjustments to make the above day-of-year calculation and figure out the number of days of difference between those local dates when they span year boundaries.

    I therefore tried to do the calculations using ordinality(of: .day, in: .era, for: date).

    However, the calculations based on calendar era give the same value regardless of the time zone of the calendar used to make do the calculation.

    Why is that?

    What would be a simpler way to calculate the number of calendar days difference between two dates WHEN EXPRESSED IN DIFFERENT LOCAL TIME ZONES? Like I said, my code that calculates the day of year would need additional logic added to handle dates that span calendar year boundaries.

    Note that this is a different question than “How many days difference is there between 2 dates”. In my question I want both dates to be expressed in different local time zones, and I’m interested in the difference in the calendar date of each of those date values.

    Solutions Collect From Internet About “Why does `ordinality(of: .day, in: .era, for: date)` give the same result for 2 dates in different time zones?”

    Martin’s comment about calendar calculations over long intervals giving unexpected results is as good an answer as any as to why it doesn’t work.

    I did come up with code that calculates the desired difference in calendar date values between 2 dates expressed in specific time zones:

    let date = Date()
    
    guard let nycTimeZone = TimeZone(abbreviation: "EST"),
      let nzTimeZone = TimeZone(abbreviation: "NZDT") else {
        fatalError()
    }
    var nycCalendar = Calendar(identifier: .gregorian)
    nycCalendar.timeZone = nycTimeZone
    var nzCalendar = Calendar(identifier: .gregorian)
    nzCalendar.timeZone = nzTimeZone
    
    let now = Date()
    
    
    let nycDateComponents = nycCalendar.dateComponents([.month, .day, .year], from: now)
    let nzDateComponents = nzCalendar.dateComponents([.month, .day, .year], from: now)
    
    let difference = Calendar.current.dateComponents([.day],
      from: nycDateComponents,
        to: nzDateComponents)
    
    let daysDifference = difference.days
    

    First I convert the 2 dates to month/day/year DateComponents values using calendars set to their specific time zone.

    Then I use the Calendar function dateComponents(_:from:to:), which lets you calculate the difference between 2 DateComponents values, in whatever units you want to use to compare them. (days, in this case)