Search code examples
swiftdatecalendariso8601

ISO8601dateformatter 1970-01-01 00:00:00 issue


How to deal with the new year and ISO8601 returning last year as year component.

To my horror, I realized ISO8601DateFormatter was returning 1977 as a year to the 1978-01-01 00:00:00

It took a while to realize this. That turned out is not wrong. Nonetheless, given the specific year of 1978, for the formatted to return 1977 is shocking.

I don't even need the timestamp. How can I reliably retrieve the specified year without having to add a second to every calendar date?

import Foundation

let datestring = "1978/1/1"
var formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(abbreviation: "UTC")
formatter.formatOptions = [.withFullDate]
let date2 = formatter.date(from: datestring) ?? Date()
print(date2)
var calendar = Calendar(identifier: .iso8601)
var year = calendar.component(.year, from: date2)
var month = calendar.component(.month, from: date2)
var day = calendar.component(.day, from: date2)
var era = calendar.component(.era, from: date2)
print("year \(year) month \(month) day \(day) era: \(era)")

===
1978-01-01 00:00:00 +0000
year 1977 month 12 day 31 era: 1

Solution

  • By default the Calendar instance will have your local timeZone. You can see this by printing print(calendar.timeZone.abbreviation() ?? "UNKNOWN"). In my case (in Seattle, WA, USA) it prints "PDT". If you simply set your calendar timezone to UTC it prints exactly what you expect:

    year 1978 month 1 day 1 era: 1