Making Date With Given Numbers

20.4k views Asked by At

I have the following Swift (Swift 3) function to make a date (Date) with date components (DateComponents).

func makeDate(year: Int, month: Int, day: Int, hr: Int, min: Int, sec: Int) -> NSDate {
    let calendar = NSCalendar(calendarIdentifier: .gregorian)!
    let components = NSDateComponents()
    components.year = year
    components.month = month
    components.day = day
    components.hour = hr
    components.minute = min
    components.second = sec
    let date = calendar.date(from: components as DateComponents)
    return date! as NSDate
}

If I use it, it will return a GMT date.

override func viewDidLoad() {
    super.viewDidLoad()
    let d = makeDate(year: 2017, month: 1, day: 8, hr: 22, min: 16, sec: 50)
    print(d) // 2017-01-08 13:16:50 +0000
}

What I actually want to return is a date (2017-01-08 22:16:50) literally based on those numbers. How can I do that with DateComponents? Thanks.

2

There are 2 answers

2
vadian On BEST ANSWER

The function does return the proper date. It's the print function which displays the date in UTC.

By the way, the native Swift 3 version of your function is

func makeDate(year: Int, month: Int, day: Int, hr: Int, min: Int, sec: Int) -> Date {
    var calendar = Calendar(identifier: .gregorian)
    // calendar.timeZone = TimeZone(secondsFromGMT: 0)!
    let components = DateComponents(year: year, month: month, day: day, hour: hr, minute: min, second: sec)
    return calendar.date(from: components)!
}

But if you really want to have UTC date, uncomment the line to set the time zone.

0
Sven On

NSDate doesn't know anything about time zones. It represents a point in time independent of any calendars or time zones. Only when printing it out like you did here it is converted to GMT. That's OK though - this is only meant for debugging. For real output use a NSDateFormatter to convert the date to a string.

As a hacky solution you might of course just configure your calendar to use GMT when creating your date object from your components. That way you will get the string you expect. Of course any other calculation with that date then might end up wrong.