Search code examples
swiftnsdatenscalendar

NSCalendar does not correct for GMT time


When I compute the start of a day, a time difference of one hour is obtained. Why is not corrected for GMT+1?

let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
cal.timeZone = NSTimeZone.localTimeZone()

let startOfToday = cal.startOfDayForDate(NSDate())

print(NSTimeZone.localTimeZone())
print(startOfToday)

Output:

"Local Time Zone (Europe/Amsterdam (GMT+1) offset 3600)\n"
"2016-01-14 23:00:00 +0000\n"

Solution

  • Your code should work fine, you shouldn't care about time zones. As already mentioned by Martin R "NSDate is an absolute point in time and does not have a timezone". If really need to use UTC time you can set the calendar property to UTC to obtain the startOfDay or noon at UTC time for any date as follow:

    extension Calendar {
        static let utc: Calendar  = {
            var calendar = Calendar.current
            calendar.timeZone = TimeZone(identifier: "UTC")!
            return calendar
        }()
        static let localTime: Calendar  = {
            var calendar = Calendar.current
            calendar.timeZone = .current
            return calendar
        }()
    }
    

    extension Date {
        var noon: Date {
            return Calendar.localTime.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
        }
        var startOfDay: Date {
            return Calendar.localTime.startOfDay(for: self)
        }
        var noonAtUTC: Date {
            return Calendar.utc.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
        }
        var startOfDayAtUTC: Date {
            return Calendar.utc.startOfDay(for: self)
        }
    }
    

    print(Date().noon)               // "2018-04-30 15:00:00 +0000\n"
    print(Date().startOfDay)         // "2018-04-30 03:00:00 +0000\n"
    
    print(Date().noonAtUTC)          // "2018-04-30 12:00:00 +0000\n"
    print(Date().startOfDayAtUTC)    // "2018-04-30 00:00:00 +0000\n"