3

When trying to convert "2016-06-23 12:00:00" to a UTC Date I get "2016-06-23 10:00:00"

The first Date is in GMT+1 which I want to convert to UTC. If I'm not mistaken GMT+0 == UTC so 12:00 should be 11:00 right? But I always get 10:00. Why is that the case and how do I convert it correctly?

I both tried this in the playground and on an actual device

This is the Code I used:

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let datestring:String = "2016-06-23 12:00:00"

    print("1: "+datestring)

    print("2: "+convertDateToUTC(datestring))

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func convertDateToUTC(_ datestring:String) -> String {

    let dateForm = DateFormatter()
    dateForm.dateFormat = "yyyy-MM-dd HH:mm:ss"
    dateForm.timeZone = TimeZone(abbreviation: "GMT+1")

    print(TimeZone.current.abbreviation()!)

    let date = dateForm.date(from: datestring)

    dateForm.timeZone = TimeZone(abbreviation: "UTC")

    let date1 = dateForm.string(from: date!)

    return date1

}

}

output:

1: 2016-06-23 12:00:00
GMT+1
2: 2016-06-23 10:00:00
abcdefg
  • 33
  • 1
  • 4

1 Answers1

9

Short answer: Replace "GMT+1" by "GMT+01".

"GMT+1" is not a valid time zone abbreviation:

 let tz = TimeZone(abbreviation: "GMT+1")
 print(tz) // nil

Therefore, in

dateForm.timeZone = TimeZone(abbreviation: "GMT+1")

you set dateForm.timeZone to nil, which means that the date string is interpreted in your default (local) timezone.

With

dateForm.timeZone = TimeZone(abbreviation: "GMT+01")

you'll get the expected result. Alternatively, create the time zone from the (numerical) GMT offset or from its identifier:

dateForm.timeZone = TimeZone(secondsFromGMT: 3600)
dateForm.timeZone = TimeZone(identifier: "GMT+0100")

Addendum (in response to your comments):

TimeZone(identifier: "GMT+0100") 
TimeZone(identifier: "Europe/Berlin")

are different time zones. The first one uses a fixed GMT offset of one hour, the second one is the time zone in a region (in this case, Germany), and differs from UTC by one or two hours, depending on whether daylight saving time is active at the specified date.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Thank you, that indeed made it work! What confuses me is that TimeZone.current.abbreviation()! gives me GMT+1 and not GMT+01... When i now put TimeZone(abbreviation: TimeZone.current.abbreviation()!) it will not work again, what should I do? – abcdefg Dec 04 '16 at 19:20
  • Aha. :))))))))) I think we should also be advising him to look at what the time zone _is_ rather than just making an assumption. – matt Dec 04 '16 at 19:20
  • 3
    @abcdefg It's best to never create a timezone from a timezone abbreviation. As you've seen, it doesn't always work. Plus there are duplicate abbreviations and plenty of invalid ones. Always use either the `identifier` or `secondsFromGMT` initializers to avoid these problems. – rmaddy Dec 04 '16 at 19:30
  • @abcdefg: I am sorry, but I don't know why `abbreviation()` returns "GMT+1" and not "GMT+01". But as rmaddy said, time zone abbreviations are highly ambiguous (some examples here: https://blogs.msdn.microsoft.com/oldnewthing/20080307-00/?p=23183). – `TimeZone(identifier: TimeZone.current.identifier)` should always give the original time zone. – Martin R Dec 04 '16 at 19:47
  • weirdly the current identifier gives me "Europe/Berlin" and applying this i end up getting 10:00 again instead of 11:00.. using TimeZone(secondsFromGMT: TimeZone.current.secondsFromGMT()) works – abcdefg Dec 04 '16 at 19:58
  • 1
    @abcdefg: "Europe/Berlin" and "GMT+01" are not the same time zone. "Europe/Berlin" is the time zone for Germany, and 2016-06-23 is during the daylight savings time. On that day, the difference to UTC is two hours. – In other words, converting "2016-06-23 12:00:00" from German time to UTC and converting "2016-06-23 12:00:00" from GMT+01 to UTC are two different things, and you have to decide which is appropriate for your application. – Martin R Dec 04 '16 at 20:03
  • Alright! Now I get it.. When changing the date to "2016-12-23 12:00:00" (in december) I do get 11:00 with the identifier for the TimeZone! Thank you guys so much I finally resolved this. I guess the TimeZones and DST's just confused me – abcdefg Dec 04 '16 at 20:08