What is wrong with this Swift TimeZone for abbreviation for a date in another timezone assumption?

Viewed 615

In an Xcode playground with the following Swift code, I get the commented output. Given a MST TimeZone object and a date that would be in the MDT TimeZone for this MST TimeZone, I do not receive the expected MDT TimeZone abbreviation output. What am I not understanding about this function, and how do I get the desired output of figuring out which of the two possible timezones a given date is in given the current example MST timezone?

// Daylight saving time (MDT) 2021 in Colorado began at 2:00 AM on Sunday, March 14
let mstDate = Date(timeIntervalSinceReferenceDate: 636327068) // "Mar 1, 2021 at 2:31 PM"
let mdtDate = Date(timeIntervalSinceReferenceDate: 637709468) // "Mar 17, 2021 at 3:31 PM"
let mstTimeZone = TimeZone(abbreviation: "MST")!
let mdtTimeZone = TimeZone(abbreviation: "MDT")!

mstTimeZone.abbreviation(for: mstDate) // expected MST, got MST
mstTimeZone.abbreviation(for: mdtDate) // expected MDT, got *****MST*****?

mdtTimeZone.abbreviation(for: mstDate) // expected MST, got MST
mdtTimeZone.abbreviation(for: mdtDate) // expected MDT, got MDT
1 Answers

Do not rely on timezone abbreviations. MST is being interpreted as "Mountain Standard Time" but it is being interpreted as Phoenix, Arizona ("America/Phoenix") instead of Denver, Colorado ("America/Denver"). You should always use timezone identifiers instead of abbreviations which are ambiguous. The timezone identifier doesn't change based on a date. What you need is to check if it is daylight saving or not for the desired date/timezone and get a timezone localized name based on it:

extension TimeZone {
    static let denverCO = Self(identifier: "America/Denver")!
    func localizedName(for date: Date) -> String { localizedName(for: isDaylightSavingTime(for: date) ? .daylightSaving : .standard, locale: .current) ?? "" }
    func localizedNameShort(for date: Date) -> String { localizedName(for: isDaylightSavingTime(for: date) ? .shortDaylightSaving : .shortStandard, locale: .current) ?? "" }
}

let mst = Date(timeIntervalSinceReferenceDate: 636327068) // "Mar 1, 2021 at 2:31 PM"
let mdt = Date(timeIntervalSinceReferenceDate: 637709468) // "Mar 17, 2021 at 3:31 PM"

TimeZone.denverCO.localizedName(for: mst)  // "Mountain Standard Time"
TimeZone.denverCO.localizedName(for: mdt)  // "Mountain Daylight Time"

TimeZone.denverCO.localizedNameShort(for: mst)  // "MST"
TimeZone.denverCO.localizedNameShort(for: mdt)  // "MDT"
Related