I am working on an app the requires checking the due date for homework. I want to know if a due date is within the next week, and if it is then perform an action.
Most of the documentation I could find is in Objective-C and I can't figure out how to do it in Swift.
Thanks for the help!!

- 6,317
- 7
- 43
- 51

- 1,991
- 3
- 14
- 13
-
2swift does not have a date class you use the Objective C NSDate class - so you have found the correct documentation – mmmmmm Oct 05 '14 at 00:52
-
Possible duplicate of [Comparing NSDates without time component](http://stackoverflow.com/questions/24577087/comparing-nsdates-without-time-component). There are lots of very good answers. – jww Oct 05 '14 at 00:56
-
Related answer: http://stackoverflow.com/questions/29652771/how-to-check-if-time-is-within-a-specific-range-in-swift/29654121#29654121 – jkdev May 09 '16 at 00:14
-
2Swift 3 does have a `Date` class. It is bridged to `NSDate`, but it is called `Date`. – BallpointBen Mar 09 '17 at 22:01
16 Answers
If you want to support ==
, <
, >
, <=
, or >=
for NSDate
s, you just have to declare this somewhere:
public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs === rhs || lhs.compare(rhs) == .OrderedSame
}
public func <(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.compare(rhs) == .OrderedAscending
}
extension NSDate: Comparable { }

- 17,460
- 4
- 46
- 50
-
This is definitely the more elegant, 'swift' way of doing this. By the way as of Swift 1.2, you need to conform to the `Equatable` protocol as well. – Isuru Jul 22 '15 at 18:55
-
2@Isuru `Comparable` is a descendant of the `Equatable` protocol so you shouldn't need to declare conformance to both. – John Estropia Jul 23 '15 at 02:00
-
@JohnEstropia Ah yes, you're right. Xcode was acting weird earlier. Btw this compares the dates down to the second, right? Is there a way to like restrict it to compare only the date parts? – Isuru Jul 23 '15 at 09:21
-
2
-
@dVaffection: Same reason you can't do this with NSStrings and NSNumbers, they're pointers. – John Estropia Dec 19 '15 at 15:48
-
-
3@dVaffection In Objective-C (where NSDate and friends are declared), if you compare using `==`, `<`, `>`, etc., you'll be getting a result of the comparison of their address in memory, not the comparison of their actual value. In Swift, they are still treated as references so I think the choice was to either (1) keep by-pointer-comparisons as they are in ObjC, or (2) eliminate confusion by not providing an implementation for comparisons. – John Estropia Dec 22 '15 at 05:01
-
2An added benefit of this approach is that `Array.maxElement()`, etc is then automatically available of arrays of NSDates. – pr1001 Jan 04 '16 at 21:02
-
I don't get it. Shouldn't the methods be inside the `extension` block? Why are they declared outside? – Marcio Cruz Feb 24 '16 at 03:06
-
1@MarcioCruz That's just a Swift requirement that all operator implementations should be at the global scope. See the discussion here: http://stackoverflow.com/questions/35246003/why-must-a-protocol-operator-be-implemented-as-a-global-function?lq=1 – John Estropia Feb 24 '16 at 04:06
-
Thanks. I think it probably uses the signature to know which "operator method" it should call. I had this doubt because i'm used to python, where operators override goes inside the class. – Marcio Cruz Feb 25 '16 at 23:31
-
1How to update first operator `==` to Swift 3? I get error that I cannot apply `===` operator to two Dates objects. Thanks – Libor Zapletal Oct 05 '16 at 21:12
-
@LiborZapletal Swift 3 Date conforms to Comparable so you don't need this anymore – Leo Dabus May 09 '18 at 11:13
I like using extensions to make code more readable. Here are a few NSDate extensions that can help clean your code up and make it easy to understand. I put this in a sharedCode.swift file:
extension NSDate {
func isGreaterThanDate(dateToCompare: NSDate) -> Bool {
//Declare Variables
var isGreater = false
//Compare Values
if self.compare(dateToCompare as Date) == ComparisonResult.orderedDescending {
isGreater = true
}
//Return Result
return isGreater
}
func isLessThanDate(dateToCompare: NSDate) -> Bool {
//Declare Variables
var isLess = false
//Compare Values
if self.compare(dateToCompare as Date) == ComparisonResult.orderedAscending {
isLess = true
}
//Return Result
return isLess
}
func equalToDate(dateToCompare: NSDate) -> Bool {
//Declare Variables
var isEqualTo = false
//Compare Values
if self.compare(dateToCompare as Date) == ComparisonResult.orderedSame {
isEqualTo = true
}
//Return Result
return isEqualTo
}
func addDays(daysToAdd: Int) -> NSDate {
let secondsInDays: TimeInterval = Double(daysToAdd) * 60 * 60 * 24
let dateWithDaysAdded: NSDate = self.addingTimeInterval(secondsInDays)
//Return Result
return dateWithDaysAdded
}
func addHours(hoursToAdd: Int) -> NSDate {
let secondsInHours: TimeInterval = Double(hoursToAdd) * 60 * 60
let dateWithHoursAdded: NSDate = self.addingTimeInterval(secondsInHours)
//Return Result
return dateWithHoursAdded
}
}
Now if you can do something like this:
//Get Current Date/Time
var currentDateTime = NSDate()
//Get Reminder Date (which is Due date minus 7 days lets say)
var reminderDate = dueDate.addDays(-7)
//Check if reminderDate is Greater than Right now
if(reminderDate.isGreaterThanDate(currentDateTime)) {
//Do Something...
}

- 3,508
- 4
- 34
- 65

- 2,912
- 1
- 18
- 5
-
28You should simplify your code. `return self.compare(dateToCompare) == NSComparisonResult.OrderedDescending` – Olav Gausaker Apr 09 '15 at 14:54
-
5isEqualToDate is provided by Apple as well. It's declaration conflicts with the one defined by Apple. – Shamas S Jun 22 '15 at 10:09
-
4
-
2I've simplified your code a bit... refactored it. As @ShamasS already pointed out, `isEqualToDate` exists already and is not needed. My result: https://gist.github.com/ppeelen/e71c4dd1c3070b3549be – Paul Peelen Nov 28 '15 at 22:00
-
1@PaulPeelen a lot better. you can easily edit your answer here. and probably `addDays` and `addHours` can be deleted as well because they are not related to the question – ReDetection Jan 18 '16 at 07:29
-
9This answer is terrible and should never be the accepted one. Don't **ever** add time intervals to dates that are created by you. That's precisely why `NSDateComponents` exist. There are a lot of edge cases that are not being handle properly and it makes no sense not to add conformance to `Comparable` to `NSDate`. I'd recommend using [John's solution](http://stackoverflow.com/a/28109990/2305521). – fpg1503 Feb 17 '16 at 21:50
-
3A better solution is to make NSDate Equatable, Comparable, then you could simply do `date1 < date2` – aryaxt Mar 11 '16 at 16:04
-
1As it is pointed out by @ShamasS this is provided since iOS 8+. Check out developer.apple.com/reference/foundation/nsdate/1416400-isequal Since iOS 10+ you can also use the == operator: https://developer.apple.com/reference/foundation/date/2293580 – iljer Nov 07 '16 at 15:02
-
In Swift 3 : self.compare(dateToCompare) == NSComparisonResult.OrderedDescending ----> self.compare(dateToCompare) == ComparisonResult.orderedDescending – Medhi Nov 17 '16 at 14:45
-
@Medhi Swift 3 Date Conforms to Comparable protocol so you can simply use `date1 < date2` – Leo Dabus May 09 '18 at 11:16
This is how you compare two NSDates in Swift, I just tested it in Xcode's playground:
if date1.compare(date2) == NSComparisonResult.OrderedDescending
{
NSLog("date1 after date2");
} else if date1.compare(date2) == NSComparisonResult.OrderedAscending
{
NSLog("date1 before date2");
} else
{
NSLog("dates are equal");
}
So to check if a date dueDate
is within a week from now:
let dueDate=...
let calendar = NSCalendar.currentCalendar()
let comps = NSDateComponents()
comps.day = 7
let date2 = calendar.dateByAddingComponents(comps, toDate: NSDate(), options: NSCalendarOptions.allZeros)
if dueDate.compare(date2!) == NSComparisonResult.OrderedDescending
{
NSLog("not due within a week");
} else if dueDate.compare(date2!) == NSComparisonResult.OrderedAscending
{
NSLog("due within a week");
} else
{
NSLog("due in exactly a week (to the second, this will rarely happen in practice)");
}

- 25,519
- 37
- 106
- 129
I always did it in one line:
let greater = date1.timeIntervalSince1970 < date2.timeIntervalSince1970
Still readable in the if
block

- 3,146
- 2
- 23
- 40
In Swift3, the Date
struct in the Foundation
now implements the Comparable
protocol. So, the previous Swift2 NSDate
approaches are superceded by Swift3 Date
.
/**
`Date` represents a single point in time.
A `Date` is independent of a particular calendar or time zone. To represent a `Date` to a user, you must interpret it in the context of a `Calendar`.
*/
public struct Date : ReferenceConvertible, Comparable, Equatable {
// .... more
/**
Returns the interval between the receiver and another given date.
- Parameter another: The date with which to compare the receiver.
- Returns: The interval between the receiver and the `another` parameter. If the receiver is earlier than `anotherDate`, the return value is negative. If `anotherDate` is `nil`, the results are undefined.
- SeeAlso: `timeIntervalSince1970`
- SeeAlso: `timeIntervalSinceNow`
- SeeAlso: `timeIntervalSinceReferenceDate`
*/
public func timeIntervalSince(_ date: Date) -> TimeInterval
// .... more
/// Returns true if the two `Date` values represent the same point in time.
public static func ==(lhs: Date, rhs: Date) -> Bool
/// Returns true if the left hand `Date` is earlier in time than the right hand `Date`.
public static func <(lhs: Date, rhs: Date) -> Bool
/// Returns true if the left hand `Date` is later in time than the right hand `Date`.
public static func >(lhs: Date, rhs: Date) -> Bool
/// Returns a `Date` with a specified amount of time added to it.
public static func +(lhs: Date, rhs: TimeInterval) -> Date
/// Returns a `Date` with a specified amount of time subtracted from it.
public static func -(lhs: Date, rhs: TimeInterval) -> Date
// .... more
}
Note ...
In Swift3, Date
is struct
, it means that it is value type
. NSDate
is class
, it is reference type
.
// Swift3
let a = Date()
let b = a //< `b` will copy `a`.
// So, the addresses between `a` and `b` are different.
// `Date` is some kind different with `NSDate`.

- 17,522
- 9
- 100
- 118
extension NSDate {
// MARK: - Dates comparison
func isGreaterThanDate(dateToCompare: NSDate) -> Bool {
return self.compare(dateToCompare) == NSComparisonResult.OrderedDescending
}
func isLessThanDate(dateToCompare: NSDate) -> Bool {
return self.compare(dateToCompare) == NSComparisonResult.OrderedAscending
}
func equalToDate(dateToCompare: NSDate) -> Bool {
return self.compare(dateToCompare) == NSComparisonResult.OrderedSame
}
}

- 412
- 6
- 10
If you want to compare dates with granularity (just same day or year etc) on swift 3.
func compareDate(date1:NSDate, date2:NSDate, toUnitGranularity: NSCalendar.Unit) -> Bool {
let order = NSCalendar.current.compare(date1 as Date, to: date2 as Date, toGranularity: .day)
switch order {
case .orderedSame:
return true
default:
return false
}
}
For other calendar comparisons change .day to;
.year .month .day .hour .minute .second

- 393
- 7
- 20
Swift already implement Date comparison just use date1 > date2 and so on.
/// Returns true if the two `Date` values represent the same point in time.
public static func ==(lhs: Date, rhs: Date) -> Bool
/// Returns true if the left hand `Date` is earlier in time than the right hand `Date`.
public static func <(lhs: Date, rhs: Date) -> Bool
/// Returns true if the left hand `Date` is later in time than the right hand `Date`.
public static func >(lhs: Date, rhs: Date) -> Bool
/// Returns a `Date` with a specified amount of time added to it.
public static func +(lhs: Date, rhs: TimeInterval) -> Date
/// Returns a `Date` with a specified amount of time subtracted from it.
public static func -(lhs: Date, rhs: TimeInterval) -> Date
/// Add a `TimeInterval` to a `Date`.
///
/// - warning: This only adjusts an absolute value. If you wish to add calendrical concepts like hours, days, months then you must use a `Calendar`. That will take into account complexities like daylight saving time, months with different numbers of days, and more.
public static func +=(lhs: inout Date, rhs: TimeInterval)
/// Subtract a `TimeInterval` from a `Date`.
///
/// - warning: This only adjusts an absolute value. If you wish to add calendrical concepts like hours, days, months then you must use a `Calendar`. That will take into account complexities like daylight saving time, months with different numbers of days, and more.
public static func -=(lhs: inout Date, rhs: TimeInterval)

- 923
- 10
- 18
in Swift 3, Date is Comparable so we can directly compare dates like
let date1 = Date()
let date2 = Date()
let isGreater = date1 > date2
print(isGreater)
let isEqual = date1 == date2
print(isEqual)
or alternatively
let result = date1.compare(date2)
switch result {
case .OrderedAscending : print("date 1 is earlier than date 2")
case .OrderedDescending : print("date 1 is later than date 2")
case .OrderedSame : print("two dates are the same")
}
better way creating extension
on Date
extension Date {
fun isGreater(than date: Date) -> Bool {
return self > date
}
func isSmaller(than date: Date) -> Bool {
return self < date
}
func isEqual(to date: Date) -> Bool {
return self == date
}
}
usage let isGreater = date1.isGreater(than: date2)

- 11,748
- 3
- 50
- 60
This function worked for me for comparing whether one date (startDate) was after the endDate where both were defined as NSDate variables:
if startDate.compare(endDate as Date) == ComparisonResult.orderedDescending

- 601
- 2
- 7
- 13
implementation in Swift
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
let files = NSFileManager.defaultManager().contentsOfDirectoryAtPath(documentsPath, error: nil)
let filesAndProperties = NSMutableArray()
for file in files! {
let filePath = documentsPath.stringByAppendingString(file as NSString)
let properties = NSFileManager.defaultManager().attributesOfItemAtPath(filePath, error: nil)
let modDate = properties![NSFileModificationDate] as NSDate
filesAndProperties.addObject(NSDictionary(objectsAndKeys: file, "path", modDate, "lastModDate"))
}
let sortedFiles = filesAndProperties.sortedArrayUsingComparator({
(path1, path2) -> NSComparisonResult in
var comp = (path1.objectForKey("lastModDate") as NSDate).compare(path2.objectForKey("lastModDate") as NSDate)
if comp == .OrderedDescending {
comp = .OrderedAscending
} else if comp == .OrderedAscending {
comp = .OrderedDescending
}
return comp
})

- 32,867
- 38
- 193
- 353
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateData: String = dateFormatter.stringFromDate(date1)
let testDate: String = dateFormatter.stringFromDate(date2)
print(dateData == testDate)

- 641
- 6
- 7
someArray.sort({($0.dateAdded?.timeIntervalSinceReferenceDate)! < ($1.dateAdded?.timeIntervalSinceReferenceDate)!})
dateAdded is an NSDate variable in my object
class MyClass {
let dateAdded: NSDate?
}

- 435
- 3
- 11
We have scenario to check current time lies b/w two times (two dates).For Example , I want to check the current lie between clinic(Hospital) opening time and closing time.
Use the simple Code.
NSDate * now = [NSDate date];
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:@"HH:mm:ss"];
//current time
NSString *currentTimeString = [outputFormatter stringFromDate:now];
NSDate *dateCurrent = [outputFormatter dateFromString:currentTimeString];
NSString *timeStart = @"09:00:00";
NSString *timeEnd = @"22:00:00";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH:mm:ss"];
NSDate *dateStart= [formatter timeStart];
NSDate *dateEnd = [formatter timeEnd];
NSComparisonResult result = [dateCurrent compare:dateStart];
NSComparisonResult resultSecond = [date2 compare:dateEnd];
if(result == NSOrderedDescending && resultSecond == NSOrderedDescending)
{
NSLog(@"current time lies in starting and end time");
}else {
NSLog(@"current time doesn't lie in starting and end time");
}

- 1,419
- 1
- 13
- 23
For swift 3, you can use the below function to compare between two dates.
func compareDate(dateInitial:Date, dateFinal:Date) -> Bool {
let order = Calendar.current.compare(dateInitial, to: dateFinal, toGranularity: .day)
switch order {
case .orderedSame:
return true
default:
return false
}
}
toGranularity can be changed according to the constraints on which you want to apply your comparison.

- 2,832
- 4
- 23
- 51
To extend on SashaZ - Swift iOS 8 and up
- Are these dates from the same day?
- Are these dates from the same month?
- is this date from a previous month than the other?
When you need more than simply bigger or smaller date comparisons. For example is it the same day or the previous day,...
Note: Never forget the timezone. Calendar timezone has a default, but if you do not like the default, you have to set the timezone yourself. To know which day it is, you need to know in which timezone you are asking.
extension Date {
func compareTo(date: Date, toGranularity: Calendar.Component ) -> ComparisonResult {
var cal = Calendar.current
cal.timeZone = TimeZone(identifier: "Europe/Paris")!
return cal.compare(self, to: date, toGranularity: toGranularity)
}
}
Use it like this:
if thisDate.compareTo(date: Date(), toGranularity: .day) == .orderedDescending {
// thisDate is a previous day
}
Of a more complex example. Find and filter all dates in an array, which are from the same day as "findThisDay":
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "Europe/Paris")
formatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
let findThisDay = formatter.date(from: "2018/11/05 08:11:08")!
_ = [
formatter.date(from: "2018/12/05 08:08:08")!,
formatter.date(from: "2018/11/05 08:11:08")!,
formatter.date(from: "2018/11/05 11:08:22")!,
formatter.date(from: "2018/11/05 22:08:22")!,
formatter.date(from: "2018/11/05 08:08:22")!,
formatter.date(from: "2018/11/07 08:08:22")!,
]
.filter{ findThisDay.compareTo(date: $0 , toGranularity: .day) == .orderedSame }
.map { print(formatter.string(from: $0)) }

- 1,574
- 19
- 18