Comparing NSDates without time component
Solution 1
Use this Calendar
function to compare dates in iOS 8.0+
func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult
passing .day
as the unit
Use this function as follows:
let now = Date()
// "Sep 23, 2015, 10:26 AM"
let olderDate = Date(timeIntervalSinceNow: -10000)
// "Sep 23, 2015, 7:40 AM"
var order = Calendar.current.compare(now, to: olderDate, toGranularity: .hour)
switch order {
case .orderedDescending:
print("DESCENDING")
case .orderedAscending:
print("ASCENDING")
case .orderedSame:
print("SAME")
}
// Compare to hour: DESCENDING
var order = Calendar.current.compare(now, to: olderDate, toGranularity: .day)
switch order {
case .orderedDescending:
print("DESCENDING")
case .orderedAscending:
print("ASCENDING")
case .orderedSame:
print("SAME")
}
// Compare to day: SAME
Solution 2
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 = Calendar.current.startOfDay(for: Date())
But, if you have to support also iOS 7, you can always write an extension
extension NSCalendar {
func myStartOfDayForDate(date: NSDate!) -> NSDate!
{
let systemVersion:NSString = UIDevice.currentDevice().systemVersion
if systemVersion.floatValue >= 8.0 {
return self.startOfDayForDate(date)
} else {
return self.dateFromComponents(self.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: date))
}
}
}
Solution 3
Xcode 11.2.1, Swift 5 & Above
Checks whether the date has same day component.
Calendar.current.isDate(date1, equalTo: date2, toGranularity: .day)
Adjust toGranularity as your need.
Solution 4
In Swift 4:
func compareDate(date1:Date, date2:Date) -> Bool {
let order = NSCalendar.current.compare(date1, to: date2, toGranularity: .day)
switch order {
case .orderedSame:
return true
default:
return false
}
}
Solution 5
I wrote the following method to compare two dates by borrowing from Ashley Mills solution. It compares two dates and returns true if the two dates are the same (stripped of time).
func compareDate(date1:NSDate, date2:NSDate) -> Bool {
let order = NSCalendar.currentCalendar().compareDate(date1, toDate: date2,
toUnitGranularity: .Day)
switch order {
case .OrderedSame:
return true
default:
return false
}
}
And it is called like this:
if compareDate(today, date2: anotherDate) {
// The two dates are on the same day.
}
Related videos on Youtube
agf119105
Updated on July 05, 2022Comments
-
agf119105 almost 2 years
In a swift playground, I have been using
NSDate.date()
But, this always appears with the time element appended. For my app I need to ignore the time element. Is this possible in Swift? How can it be done? Even if I could set the time element to be the same time on every date that would work too.
Also, I am trying to compare two dates and at the moment I am using the following code:
var earlierDate:NSDate = firstDate.earlierDate(secondDate)
Is this the only way or can I do this in a way that ignores the time element? For instance I don't want a result if they are the same day, but different times.
-
The Paramagnetic Croissant almost 10 yearsYou don't want to "ignore" the time part of the object. It seems that you want to format the date as a string without the time part. You can do that using
NSDateFormatter
.
-
-
agf119105 almost 10 yearsThanks, Could you answer the how as well?!?
-
The Paramagnetic Croissant almost 10 years@agf119105 using Google, for instance.
-
vikingosegundo almost 10 yearsIt answers the question as it wording, isn't it?
-
vikingosegundo almost 10 yearsah, come on, string operations?
-
agf119105 almost 10 yearsThe wording of the question: "Is this possible in Swift? How can it be done?" meaning what code is required? @user3477950 tried Google thanks, but no useful results for Swift ...
-
agf119105 almost 10 yearsthis doesn't help as I know how to print a localised description without the time element. I want to ignore the time-element as I need to compare two dates without the time getting in the way
-
Léo Natan almost 10 years@agf119105 In that case, use
NSDateComponents
. -
vikingosegundo almost 10 yearsis this from UIKit? I cannot find it in a Foundation project.
-
Ashley Mills almost 10 yearsThis is one of the new iOS 8.0
NSCalendar
APIs. SeeNSCalendar.h
in iOS 7.1 to iOS 8.0 API Differences -
vikingosegundo almost 10 yearsfinally, I always missed it.
-
agf119105 almost 10 yearsThanks Ashley, really appreciate this answer - as I am such a beginner, if you have time could you some me how to use this? @AshleyMills
-
Yer00n over 9 yearsNot quite. The NSDate type represents a point in time; it contains date elements and time elements. So your code compares two points in time as opposed to the intended calendar dates in the original question.
-
Duncan C almost 9 yearsThe new NSCalendar methods like
compareDate:toDate:toUnitGranularity:
look very cool, but they're not in the Xcode docs or the online docs either. Where did you learn about them? -
Duncan C almost 9 yearsSwift doesn't even let me command-click on the method name to find it in the framework headers. I had to command-click on NSCalendar and look in it's header to find the method definition.
-
Ashley Mills almost 9 yearsI found them in the iOS 8.0 API diffs document - these are always worth a read, all kinds of goodies appear in there! developer.apple.com/library/ios/releasenotes/General/…
-
the Reverend over 8 yearsWhats is the __NSDate type and _NSCopyOnWriteCalendarWrapper ?
-
Ashley Mills over 8 years@theReverend that was a hangover from an old version of Swift. Updated for 2.0 - thanks!
-
jaw about 8 yearsI think the two comments, indicating the expected results are wrong.
// Compare to day: DESCENDING
should beSAME
and vice versa. -
Ashley Mills over 3 yearsThis is an identical copy of @zs2020 answer from 18 months earlier
-
Ângelo Polotto over 3 yearsother logic operator, like
<
,>
,>=
and<=
, works as well.