Search code examples
swifttimestamputclocaltimedatetime-conversion

From UTC to local time doesn't consider daylight saving swift


I am using this function to convert UTC time to my local time stamp.

    func UTCToLocal(date:String, timeZone: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "H:mm:ss"
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    let dt = dateFormatter.date(from: date)
    dateFormatter.timeZone = TimeZone(identifier: timeZone)
    dateFormatter.dateFormat = "h:mm a"
    return dateFormatter.string(from: time)
}

But this doesn't check DST. So, I am getting one hour difference. Can anyone help me with some general solution for this problem?


Thanks to Leo who have figured out the issue. I have updated the functions as:

    func UTCToLocal(date:String, timeZone: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    dateFormatter.locale = Locale(identifier: "en_US_POSIX")
    dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
    let dt = dateFormatter.date(from: date)
    dateFormatter.timeZone = TimeZone(identifier: timeZone)
    dateFormatter.dateFormat = "dd-MM-yyyy hh:mm aa"
    return dateFormatter.string(from: dt!)
}

Now the date string in function paramter have value in this format "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'". This solves the issue.


Solution

  • The issue here is the lack of the date. You are always passing only the time components without the day so the daylight savings time Will always be correspondent to January 1st 2001. If you need today’s date you need to set the date formatter defaultDate property to the startOfDay for today. Btw don’t forget to set the locale first to “en_US_POSIX” before setting the fixed date format. Btw you should never escape the Z. It will ignore the timezone of the date string. You should take a look at this post on how to create and parse a iso8601 date