Comparing NSDates without time component

55,281

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.
}
Share:
55,281

Related videos on Youtube

agf119105
Author by

agf119105

Updated on July 05, 2022

Comments

  • agf119105
    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
      The Paramagnetic Croissant almost 10 years
      You 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
    agf119105 almost 10 years
    Thanks, Could you answer the how as well?!?
  • The Paramagnetic Croissant
    The Paramagnetic Croissant almost 10 years
    @agf119105 using Google, for instance.
  • vikingosegundo
    vikingosegundo almost 10 years
    It answers the question as it wording, isn't it?
  • vikingosegundo
    vikingosegundo almost 10 years
    ah, come on, string operations?
  • agf119105
    agf119105 almost 10 years
    The 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
    agf119105 almost 10 years
    this 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
    Léo Natan almost 10 years
    @agf119105 In that case, use NSDateComponents.
  • vikingosegundo
    vikingosegundo almost 10 years
    is this from UIKit? I cannot find it in a Foundation project.
  • Ashley Mills
    Ashley Mills almost 10 years
    This is one of the new iOS 8.0 NSCalendar APIs. See NSCalendar.h in iOS 7.1 to iOS 8.0 API Differences
  • vikingosegundo
    vikingosegundo almost 10 years
    finally, I always missed it.
  • agf119105
    agf119105 almost 10 years
    Thanks 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
    Yer00n over 9 years
    Not 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
    Duncan C almost 9 years
    The 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
    Duncan C almost 9 years
    Swift 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
    Ashley Mills almost 9 years
    I 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
    the Reverend over 8 years
    Whats is the __NSDate type and _NSCopyOnWriteCalendarWrapper ?
  • Ashley Mills
    Ashley Mills over 8 years
    @theReverend that was a hangover from an old version of Swift. Updated for 2.0 - thanks!
  • jaw
    jaw about 8 years
    I think the two comments, indicating the expected results are wrong. // Compare to day: DESCENDING should be SAME and vice versa.
  • Ashley Mills
    Ashley Mills over 3 years
    This is an identical copy of @zs2020 answer from 18 months earlier
  • Ângelo Polotto
    Ângelo Polotto over 3 years
    other logic operator, like <, >, >= and <=, works as well.