Search code examples
iosswifttimezonegregorian-calendarnstimezone

User timezone issues


My app was working fine until the changing of the clocks this morning. I set the user's timezone using the following code.

let usersTimeZone: String = ltzAbbrev()
var gregorian: NSCalendar = NSCalendar(calendarIdentifier: NSISO8601Calendar)!
gregorian.timeZone = NSTimeZone(abbreviation: usersTimeZone)!

The code worked above until the clocks went forward this morning and now ltzAbbrev() is returning GMT+1 and this is causing my program to crash with the standard error

fatal error: unexpectedly found nil while unwrapping an Optional value


Solution

  • It seems that you are using the function

    func ltzAbbrev() -> String { return NSTimeZone.localTimeZone().abbreviation! }
    

    from https://stackoverflow.com/a/27053592/1187415. So with

    let usersTimeZone:String = ltzAbbrev()
    gregorian.timeZone = NSTimeZone(abbreviation: usersTimeZone)!
    

    you are doing two conversions

    time zone -> abbreviation -> time zone
    

    and that does not work reliably, as stated in the NSTimeZone documentation:

    In general, you are discouraged from using abbreviations except for unique instances such as “UTC” or “GMT”. Time Zone abbreviations are not standardized and so a given abbreviation may have multiple meanings—for example, “EST” refers to Eastern Time in both the United States and Australia

    It is also not necessary, since you can simply set

    gregorian.timeZone = NSTimeZone.localTimeZone()
    

    instead.

    Another (unrelated) problem might be the usage of NSISO8601Calendar, as the NSLocale documentation states

    Identifier for the ISO8601. The ISO8601 calendar is not yet implemented.

    The Gregorian calendar is obtained with

    let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!