Robert Gummesson
Robert Gummesson

Reputation: 5666

Swift - Timezone off by one hour / secondsFromGMT incorrect

This should be a really simple question but I just can't seem to wrap my head around it.

Given my timezone is EDT (GMT-4), why does 04:00 in GMT turn into 23:00 and not 00:00?

// The offset is -4 hours
let offsetFromGMT = Calendar.current.timeZone.secondsFromGMT() / 60 / 60

// 2017-03-12 04:00
var destinationComponents = DateComponents()
destinationComponents.timeZone = TimeZone(secondsFromGMT: 0)
destinationComponents.year = 2017
destinationComponents.month = 03
destinationComponents.day = 12
destinationComponents.hour = -offsetFromGMT // 4 hours

// Why is this 2017-03-11 23:00 and not 2017-03-12 00:00?
let date = Calendar.current.date(from: destinationComponents)!
// Outputs 23
Calendar.current.dateComponents([.hour], from: date).hour

Upvotes: 2

Views: 7233

Answers (1)

Martin R
Martin R

Reputation: 540095

Calendar.current.timeZone.secondsFromGMT()

is the current GMT offset for your time zone. In your case that is 4 hours, because the current time zone in New York is EDT = GMT-4, with daylight saving time active.

So your destinationComponents and date are four o'clock in the morning Greenwich time:

2017-03-12 04:00:00 +0000

At that point, the time zone in New York was EST = GMT-5, and daylight saving time not active. Therefore that date is 2017-03-11 23:00 in your local time zone.


I would proceed differently, avoiding "secondsFromGMT".

Example: "2017-03-12 00:00:00" New York time is "2017-03-12 05:00:00" GMT.

var srcComponents = DateComponents()
srcComponents.timeZone = TimeZone(identifier: "America/New_York")!
srcComponents.year = 2017
srcComponents.month = 3
srcComponents.day = 12
srcComponents.hour = 0
srcComponents.minute = 0

let date = Calendar.current.date(from: srcComponents)!
print(date) // 2017-03-12 05:00:00 +0000

Upvotes: 8

Related Questions