Search code examples
swiftdatensdateformatterdateformatter

26 March of 1995 could not be mapped into date using Europe/Sofia timezone


DateFomatter could not init the date from "1995-03-26" string when using "Europe/Sofia" timezone. I've also tried to use different timezones and everything works correctly, but not for this specific timezone. What is the reason for this strange behaviour?

import Foundation

let serverLocalDateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.dateFormat = "yyyy-MM-d"
    formatter.timeZone = TimeZone(secondsFromGMT: 60 * 60 * 2)
    
    return formatter
}()

let serverLocalDateFormatter2: DateFormatter = {
    let formatter = DateFormatter()
    
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.dateFormat = "yyyy-MM-d"
    formatter.timeZone = TimeZone(identifier: "Europe/Sofia")
    
    return formatter
}()

let testCase1 = "1995-03-26"
let testCase2 = "1995-03-27"
let testCase3 = "1995-03-25"

serverLocalDateFormatter.date(from: testCase1)
serverLocalDateFormatter2.date(from: testCase1)
serverLocalDateFormatter.date(from: testCase2)
serverLocalDateFormatter.date(from: testCase3)

I've created date formatter and used `date(from: String) method to get the date from the string that is returned from the backend, but only one specific date could not be parsed.Playground with bug


Solution

  • The formatter assumes the string represents a date with the time 00:00:00, but the datetime 1995-03-26T00:00:00 doesn't exist in Bulgaria's timezone, because this is when a Bulgaria transitions into daylight saving time in 1995, "skipping" a whole hour starting from 00:00:00.

    You can set isLenient to true to have it return the start of the day of 1995-03-26, which is at 1am.

    formatter.isLenient = true
    

    Having the formatter be lenient also allows for other "malformed" dates like "1995-03-32" to be successfully parsed, but since this seems to be parsing dates that come from a server, this shouldn't matter too much.