1st april dates of 80s failed to parse in iOS 10.0

This problem occurs if daylight saving time starts exactly on
midnight, as it was the case in Moscow in the years 1981–1984 (see for example Clock Changes in Moscow, Russia (Moskva)).

This was also observed in

For example, at midnight of April 1st 1984, the clocks were adjusted one hour forward, which means that the date “1984-04-01 00:00”
does not exist in that timezone:

let dFmt = DateFormatter()
dFmt.dateFormat = "yyyy-MM-dd"
dFmt.timeZone = TimeZone(identifier: "Europe/Moscow")
print(dFmt.date(from: "1984-04-01")) // nil

As a solution, you can tell the date formatter to be “lenient”:

dFmt.isLenient = true

and then it will return the first valid date on that day:

dFmt.isLenient = true
if let date = dFmt.date(from: "1984-04-01") {
    dFmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
    print(dFmt.string(from: date)) 
}
// 1984-04-01 01:00:00

A different solution
was given by rob mayoff, which is to make the date formatter use noon instead of midnight as the
default date. Here is a translation of rob’s code from Objective-C to Swift:

let noon = DateComponents(calendar: dFmt.calendar, timeZone: dFmt.timeZone,
               year: 2001, month: 1, day: 1, hour: 12, minute: 0, second: 0)
dFmt.defaultDate = noon.date
if let date = dFmt.date(from: "1984-04-01") {
    dFmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
    print(dFmt.string(from: date)) 
}
// 1984-04-01 12:00:00

Leave a Comment