Moebius
Moebius

Reputation: 700

Swift 3 - Time Part of Date And Different Timezones

I am having an issue with a date string received from a REST web service and how that is being represented in Swift in different timezones. I have just been able to reproduce this issue, so I am going to relate this specific example.

The information I am getting from the web service is a date-time string and a timezone identifier. In this case, the system is in the America/New_York or Eastern US timezone. I created a playground where I have the following code

let dateFormatString = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let easternTimeZone = "America/New_York"
let serverDate = "2017-03-01T00:00:00-05:00"

I have a method that takes the date string and the timezone identifier and creates a Date object as follows

func dateForDateString(dateString: String, timeZone: String) -> Date?
{
    let formatter = DateFormatter()
    if timeZone != ""
    {
        formatter.timeZone = TimeZone(identifier: timeZone)
    }

    formatter.dateFormat = dateFormatString

    return formatter.date(from: dateString)
}

When I call this method with what's returned from the web service

let easternDate = dateForDateString(dateString: serverDate, timeZone: easternTimeZone)
print("\(easternDate)")

The print statement outputs Optional(2017-03-01 05:00:00 +0000) which is expected. No problems yet. The problem happens when the device is in a different timezone and for the sake of this example, I am testing with Pacific time. In the playground, the easternTime variable shows as Feb 28, 2017, 9:00 PM. Again, not unexpected.

The date is going to be stored in a Firebase database and I don't care about the time at all. So I end up using the Calendar method startOfDay as follows

let myDate = Calendar.current.startOfDay(for: ed)

as you may expect, this returns the Date Feb 28, 2017, 12:00 AM. Obviously not what I want to store in Firebase. The bottom line is that I need the date to be in the timezone the web service returned.

UPDATE As mentioned in the comments, I also tried to create a Calendar instance and set it's timeZone property to a TimeZone with the identifier received from the server. The code looks like this

var easternCal = Calendar(identifier: .gregorian)
if let etz = TimeZone(identifier: easternTimeZone)
{
    easternCal.timeZone = etz
}

if let ed = easternDate
{
    let convertedDate = dateToTimeZone(date: ed, toTimezone: easternTimeZone)
    let currentCalDate = Calendar.current.startOfDay(for: ed)
    let myDate = easternCal.startOfDay(for: ed)
    print("\(myDate)")
}

Last night, I could have sworn this didn't work, but when I try it now in the playground, it appears to be working just fine. currentCalDate is the date I don't want, Feb 28, 2017, 12:00 AM since it is using the user's Calendar that has the Pacific timezone set. myDate is correctly showing as Feb 28, 2017, 9:00 PM, which is printing as 2017-03-01 05:00:00 +0000, what I have wanted all along.

I think this one is solved.

Upvotes: 1

Views: 684

Answers (1)

Moebius
Moebius

Reputation: 700

As mentioned in the update to my question, creating a Calendar instance and setting the timeZone property to the one returned from the back-end solved my problem.

Upvotes: 1

Related Questions