user2908412
user2908412

Reputation: 107

Converting time from GMT in iOS behaving oddly (Reverse)

So I am trying to convert some times I receive in UTC/GMT to the local time zone using the following code:

let gmtFormatter: NSDateFormatter = NSDateFormatter()
gmtFormatter.timeZone = NSTimeZone(name: "GMT")
gmtFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let gmtDate: NSDate = gmtFormatter.dateFromString(dateString)!
print("GMT \(gmtDate)")
let localFormatter: NSDateFormatter = NSDateFormatter()
localFormatter.timeZone = NSTimeZone.localTimeZone()
localFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let localDate: NSDate = localFormatter.dateFromString(gmtFormatter.stringFromDate(gmtDate))!
        print("Local \(localDate)")

However, I find that the conversion is working in revers. PST is UTC-8 and the outputs are 8 hours ahead instead of 8 hours behind. So I tested with a London Time Zone (CET) which is UTC+1 and should be 1 hour ahead of GMT. The results was a time that was 1 hour behind.

This was the string I am testing with: "2016-02-24 00:05:54"

For PST this should convert to 2016-02-23 04:05:54, but instead converts to 2016-02-24 08:05:54 (notice the way it should be is on the 23rd and not the 24th)

For CET this should convert to 2016-02-24 01:05:54, but instead converts to 2016-02-23 23:05:54 (notice the way it should be is on the 24th and not the 23rd)

Am I missing something glaring?

Upvotes: 1

Views: 1103

Answers (1)

matt
matt

Reputation: 534925

The problem is that in the second part of your code...

let localDate: NSDate = 
    localFormatter.dateFromString(gmtFormatter.stringFromDate(gmtDate))!

... you're doing the opposite of what you want. An NSDate is absolute. Its string representation is what is volatile, as it were. So having turned a string into a date with your first formatter, what you now want to do is turn that date into a string with your second formatter.

For example, I'm in California. Now, watch this:

let dateString = "2016-02-24 10:09:08"
let gmtFormatter: NSDateFormatter = NSDateFormatter()
gmtFormatter.timeZone = NSTimeZone(name: "GMT")
gmtFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let gmtDate: NSDate = gmtFormatter.dateFromString(dateString)!
print("GMT \(gmtDate)")
let localFormatter: NSDateFormatter = NSDateFormatter()
localFormatter.timeZone = NSTimeZone.localTimeZone()
localFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let localDateString = localFormatter.stringFromDate(gmtDate) // <-- !!!
print("Local \(localDateString)")

Result:

GMT 2016-02-24 10:09:08 +0000
Local 2016-02-24 02:09:08

That's correct. When it's 10 AM in London, it's 2 AM here.

To put it another way, if you think what you're doing is converting a date from one time zone to another, you have not understood what a date is. It is a date-time and a time zone. There is nothing to convert: it is completely determined, and it is correct no matter where you are, because it says what time zone it is.

Perhaps it would be a bit clearer to you if I changed the next-to-last line format to this:

localFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"

The final output is then:

Local 2016-02-24 02:09:08 -0800

which is obviously correct.

Upvotes: 5

Related Questions