NSDate objects represent a single point in time. NSDate is a class cluster; its single public superclass, NSDate, declares the programmatic interface for specific and relative time values. The objects you create using NSDate are referred to as date objects.
NSDate is an abstract class that provides behavior for creating dates, comparing dates, representing dates, computing intervals, and similar functionality. NSDate presents a programmatic interface through which suitable date objects are requested and returned. Date objects returned from NSDate are lightweight and immutable since they represent an invariant point in time.
Using NSDate
In objective-c, the following code results in the UTC date time information using the date API.
NSDate *currentUTCDate = [NSDate date]
In Swift however,
let date = NSDate()
Results in local date and time.
UTC vs Local Time
NSDate is a specific point in time without a time zone. Think of it as the number of seconds that have passed since a reference date. How many seconds have passed in one time zone vs. another since a particular reference date? The answer is the same.
Depending on how you output that date (including looking at the debugger), you may get an answer in a different time zone.
If they ran at the same moment, the values of these are the same. They’re both the number of seconds since the reference date, which may be formatted on output to UTC or local time. Within the date variable, they’re both UTC.
To explain this, we can use a NSDateFormatter in a playground:
import UIKit let date = NSDate(); // "Apr 1, 2015, 8:53 AM" <-- local without seconds var formatter = NSDateFormatter(); formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"; let defaultTimeZoneStr = formatter.stringFromDate(date); // "2015-04-01 08:52:00 -0400" <-- same date, local, but with seconds formatter.timeZone = NSTimeZone(abbreviation: "UTC"); let utcTimeZoneStr = formatter.stringFromDate(date); // "2015-04-01 12:52:00 +0000" <-- same date, now in UTC
Compare NSDate
If you need to compare two dates, you can use the method below. This example shows comparing the current date against an endDate. It will give you all possible results so you can handle each situation.
// Date comparision to compare current date and end date. var dateComparisionResult:NSComparisonResult = NSDate().compare(endDate) if dateComparisionResult == NSComparisonResult.OrderedAscending { // Current date is smaller than end date. } else if dateComparisionResult == NSComparisonResult.OrderedDescending { // Current date is greater than end date. } else if dateComparisionResult == NSComparisonResult.OrderedSame { // Current date and end date are same. }
There are several useful methods in NSCalendar in iOS 8.0+:
startOfDayForDate, isDateInToday, isDateInYesterday, isDateInTomorrow
And even to compare days:
func isDate(date1: NSDate!, inSameDayAsDate date2: NSDate!) -> Bool
To ignore the time element you can use this:
var toDay = NSCalendar.currentCalendar().startOfDayForDate(NSDate())
Formatting NSDate
If you have a string and want to convert it to an NSDate.
var dataString = "April 1, 2015" as String var dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "MM-dd-yyyy" dateFormatter.timeZone = NSTimeZone.localTimeZone() // convert string into date let dateValue = dateFormatter.dateFromString(dataString) as NSDate! println(dateValue)
This might help you also formatting your dates:
Convert Unix TimeStamp to NSDate in Swift
If you have a timestamp "/Date(1427909016000-0800)" and you need to convert it to an NSDate, you can use the following extension. This will also convert it to your local time. The first part "1427909016000" is the time since the Unix epoch in milliseconds, and the second part "-0800" is a time zone specification.
extension NSDate { convenience init?(jsonDate: String) { let prefix = "/Date(" let suffix = ")/" let scanner = NSScanner(string: jsonDate) // Check prefix: if scanner.scanString(prefix, intoString: nil) { // Read milliseconds part: var milliseconds : Int64 = 0 if scanner.scanLongLong(&milliseconds) { // Milliseconds to seconds: var timeStamp = NSTimeInterval(milliseconds)/1000.0 // Read optional timezone part: var timeZoneOffset : Int = 0 if scanner.scanInteger(&timeZoneOffset) { let hours = timeZoneOffset / 100 let minutes = timeZoneOffset % 100 // Adjust timestamp according to timezone: timeStamp += NSTimeInterval(3600 * hours + 60 * minutes) } // Check suffix: if scanner.scanString(suffix, intoString: nil) { // Success! Create NSDate and return. self.init(timeIntervalSince1970: timeStamp) return } } } // Wrong format, return nil. (The compiler requires us to // do an initialization first.) self.init(timeIntervalSince1970: 0) return nil } }
Here's an example of it in use:
if let theDate = NSDate(jsonDate: "/Date(1427909016000-0800)/") { println(theDate) } else { println("wrong format") }
Result
2015-04-01 09:23:36 +0000