Localized Date/Time, XCode 7, Swift 2

Hi


I'm in need of getting a localized Date. Here is some of my code so far for getting a date (this is from a ble characteristic, but that probably doesn't matter).


            let timeNow: NSDate = NSDate()
            let negMinutes = -1*Int(timestamps[0])
            let dateStarted: NSDate = NSCalendar.currentCalendar().dateByAddingUnit(NSCalendarUnit.Minute, value: negMinutes, toDate: timeNow, options: [])!
            print("\n         Date/Time UTC Started: \(dateStarted)")
           
            let dateFormatter = NSDateFormatter()
            dateFormatter.dateStyle = NSDateFormatterStyle.LongStyle
            dateFormatter.timeStyle = NSDateFormatterStyle.LongStyle
            let dateStartedLocal = dateFormatter.stringFromDate(dateStarted!)
            print("         Date/Time Started Local Str: \(dateStartedLocal)")

            dateFormatter.locale = NSLocale.currentLocale()
            let localStartDate: NSDate = dateFormatter.dateFromString(dateStartedLocal)!
            print("         Date/Time Started NSDate: \(localStartDate)\n")


The output for the above code is:



Date/Time UTC Started: Optional(2016-10-17 11:40:29 +0000)

Date/Time Started Local Str: October 17, 2016 at 7:40:29 AM EDT

Date/Time Started NSDate: 2016-10-17 11:40:29 +0000


The first date/time is UTC which then gets converted to local date/time. But when I try to generate an NSDate from the localized date string it goes back to UTC. I want it to stay as the localized date, but as an NSDate. Any idea what I'm doing wrong?


I'm also curious what that "Optional" part of the first date/time output is, but it may not be important.


Thanks...

Replies

I run this without problem in playground. And no optional


I had to do some changes:

- delete *Int(timestamps[0]) : what is this ? May be that's the cause of optional, ;

try *Int(timestamps[0])! if yoy are sure it's convertible to Int


- delete the unwrap for dateStarted in

let dateStartedLocal = dateFormatter.stringFromDate(dateStarted!)

NSDate (and Swift 3’s

Date
) does not support the concept of time zones. Under the covers an NSDate is actually a floating point count of the number of seconds since the reference date (the start of 2001). NSDate’s
-description
method always returns a UTC string to reinforce that fact.

Generally you should use NSDate to hold date values and then use NSDateFormatter when you want to ‘render’ those values to something the user can read (or parse values the user has entered). However, there are circumstances where it makes sense to store other things (like NSDateComponents).

In your specific case, AFAICT, you just want to calculate an NSDate from an offset in minutes relative to the current date. You don’t need to involve calendar to do this. Rather, you can do it with simple maths:

import Foundation

let deltaMinutes: NSTimeInterval = -35.0
let now = NSDate()
let then = NSDate(timeIntervalSinceNow: deltaMinutes * 60.0)
print(now)
print(then)

For example, running this produces:

2016-10-20 08:43:34 +0000
2016-10-20 08:08:34 +0000

This is safe to do for minutes (and any smaller units) because small time units are the same in all calendars. If this were hours then things get tricky, because you have to decide what ‘N hours from now’ means when crossing a time discontinuity (like a daylight savings transition).

Date and time programming is really hard to get right in the general case. I recommend you watch WWDC 2011 Session 117 Performing Calendar Calculations, which describes some of the really gnarly edge cases.

Also, if you have specific questions feel free to post them here. Try to describe what you’re high-level goạl is, rather than getting bogged down in the code, because we need that context in order to give the best advice.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"