Artem
Artem

Reputation: 228

How to get daylight saving time with using pod TimeZoneLocate in Swift

I'm converting local timezone to string to display it on screen. For this purpose I use TimeZoneLocate library. Problem: I'm getting date result one hour less than it is because of not implementing daylight saving time.

I'm getting JSON from sunrise-sunset.org, and using this lines: sunrise = "3:22:31 AM"; sunset = "5:23:25 PM".

I thought about using function isDaylightSavingTime() with if statement, but I can't figure out where to add this one hour.

This is function where does the magic happen:

func UTCToLocal(incomingFormat: String, outgoingFormat: String, location: CLLocation?) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = incomingFormat
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")

    let dt = dateFormatter.date(from: self)
    let timeZone = location?.timeZone ?? TimeZone.current

    dateFormatter.timeZone = timeZone
    dateFormatter.dateFormat = outgoingFormat

    return dateFormatter.string(from: dt ?? Date())
}

I use local "location" from CLLocation, TimeZone.current is provided by TimeZoneLocate library.

This is how I use it in code:

func parce(json: Data, location: CLLocation) {
    let decoder = JSONDecoder() 
if let sunriseData = try? decoder.decode(Results.self, from: json) {

self.sunriseLbl.text = sunriseData.results?.sunrise.UTCToLocal(incomingFormat: "h:mm:ss a",
outgoingFormat: "HH:mm",
location: location)

sunriseLbl is printing the sunrise data from JSON for current location by default and for any place by GooglePlaces. But, in both, I get wrong date.

Also, here is a link to my project on GitHub, if it might help you help me: https://github.com/ArtemBurdak/Sunrise-Sunset.

Thanks in advance

Upvotes: 0

Views: 1435

Answers (1)

David Chopin
David Chopin

Reputation: 3064

An interesting thing I noted: TimeZone.current is returning the correct time zone, but location?.timeZone is not returning the correct time zone. If there is a way to implement TimeZone.current, i.e. the application will always be using the user's current location, then I would advise using that. If users can enter a custom location, however, then you need to get a workaround for the apparent incorrect time zone returned by location?.timeZone.

My workaround is as follows. Notice that we manually adjust the location of the time zone we want by changing the .secondsFromGMT() property. This is how I adjusted your code, and it was returning the correct time zone for my personal location.

extension String {
    func UTCToLocal(incomingFormat: String, outgoingFormat: String, location: CLLocation?) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = incomingFormat
        dateFormatter.timeZone = TimeZone(abbreviation: "UTC")

        let dt = dateFormatter.date(from: self)

        var timeZone = location?.timeZone ?? TimeZone.current

        if timeZone.isDaylightSavingTime() {
            timeZone = TimeZone(secondsFromGMT: timeZone.secondsFromGMT() - 7200)!
        }
        dateFormatter.timeZone = timeZone
        dateFormatter.dateFormat = outgoingFormat

        let output = dateFormatter.string(from: dt ?? Date())

        return output
    }
}

NOTE: Time zones are very complex and change from place to place and from the current time of year. Just because this workaround works for my current location on this current day, doesn't mean that this workaround always works. However, you can look at the timeZone.isDaylightSavingTime() value returned as well as the current location to create a new time zone via timeZone = TimeZone(secondsFromGMT: timeZone.secondsFromGMT() - x as needed. This is the way you can implement the

"I thought about using function isDaylightSavingTime() with if statement, but I can't figure out where to add this one hour."

idea that you had.

EDIT: For the record, the time zone I was using was CST, or Chicago time. The date I wrote this code at was April 19, 2019.

Upvotes: 1

Related Questions