没有时间组件的NSDate比较

86
在 Swift Playground 中,我一直在使用:
NSDate.date() 

但是,这通常会附加时间元素。对于我的应用程序,我需要忽略时间元素。在Swift中是否有可能实现?如何做到?即使我可以将时间元素设置为每个日期上相同的时间,那也可以。

此外,我正在尝试比较两个日期,目前我正在使用以下代码:

var earlierDate:NSDate = firstDate.earlierDate(secondDate)

这是唯一的方法吗?还是有另一种方式可以忽略时间元素?比如说,我不想在同一天但不同时间得到结果。


1
你不想“忽略”对象的时间部分。看起来你想将日期格式化为没有时间部分的字符串。你可以使用NSDateFormatter来实现这个目的。 - The Paramagnetic Croissant
17个回答

156

使用此 Calendar 函数来比较 iOS 8.0+ 中的日期。

func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult


.day作为单位传递给函数

使用此函数的方法如下:

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

这是来自UIKit吗?我在Foundation项目中找不到它。 - vikingosegundo
2
这是新的iOS 8.0 NSCalendar API之一。请参阅iOS 7.1到iOS 8.0 API差异中的NSCalendar.h - Ashley Mills
1
最后,我总是错过它。 - vikingosegundo
1
@theReverend 这是来自旧版Swift的问题。已经更新至2.0版本了,谢谢! - Ashley Mills
2
我认为这两个注释中所指示的预期结果是错误的。// Compare to day: DESCENDING 应该是 SAME,反之亦然。 - jaw
显示剩余5条评论

28

Xcode 11.2.1,Swift 5及以上版本

检查日期是否具有相同的日期组件。

Calendar.current.isDate(date1, equalTo: date2, toGranularity: .day)

根据您的需要调整粒度。


22

iOS 8.0+中NSCalendar有几种有用的方法:

startOfDayForDate, isDateInToday, isDateInYesterday, isDateInTomorrow

甚至可以比较日期:

func isDate(date1: NSDate!, inSameDayAsDate date2: NSDate!) -> Bool

如果要忽略时间元素,可以使用以下方法:

var toDay = Calendar.current.startOfDay(for: Date())

但是,如果您还需要支持iOS 7,您可以编写一个扩展程序

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))
        }
    }
}

11

在 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
    }
}

8

我编写了一个用于比较两个日期的Swift 4扩展:

import Foundation

extension Date {      
  func isSameDate(_ comparisonDate: Date) -> Bool {
    let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
    return order == .orderedSame
  }

  func isBeforeDate(_ comparisonDate: Date) -> Bool {
    let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
    return order == .orderedAscending
  }

  func isAfterDate(_ comparisonDate: Date) -> Bool {
    let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
    return order == .orderedDescending
  }
}

使用方法:

startDate.isSameDateAs(endDate) // 返回 true 或 false


这段代码与日期相关,用于比较两个日期是否相同。

8

我借鉴了Ashley Mills的方法编写了以下函数,用于比较两个日期。它会比较两个日期并在它们相同(不考虑时间)时返回true。

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
    }
}

它被称为这样:

if compareDate(today, date2: anotherDate) {
    // The two dates are on the same day.
}

7
在Swift中比较两个日期。
    // Date comparision to compare current date and end date.
    var dateComparisionResult:NSComparisonResult = currentDate.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.
    }

5
不完全正确。NSDate类型代表一个时间点;它包含日期元素和时间元素。因此,您的代码比较的是两个时间点,而不是原问题中预期的日历日期。 - Yer00n

6

为了支持iOS7

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date1String = dateFormatter.stringFromDate(date1)
let date2String = dateFormatter.stringFromDate(date2)
if date1String == date2String {
    println("Equal date")
}

其他逻辑运算符,如 <>>=<=,同样有效。 - Ângelo Polotto

5
您可以使用日期的描述来比较两个日期。
let date1 = NSDate()
let date2 = NSDate(timeIntervalSinceNow: 120)
if date1.description == date2.description {
    print(true)
} else {
    print(false)   // false (I have added 2 seconds between them)
}

如果您想将日期的时间元素设置为不同的时间,可以按照以下方法操作:
extension NSDate {
    struct Calendar {
        static let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    }
    var day:    Int { return Calendar.gregorian.component(.Day,    fromDate: self)   }
    var month:  Int { return Calendar.gregorian.component(.Month,  fromDate: self)  }
    var year:   Int { return Calendar.gregorian.component(.Year,   fromDate: self)  }

    var noon: NSDate {
        return Calendar.gregorian.dateWithEra(1, year: year, month: month, day: day, hour: 12, minute: 0, second: 0, nanosecond: 0)!
    }
}

let date1 = NSDate()
let date2 = NSDate(timeIntervalSinceNow: 120)
print(date1.noon == date2.noon)   // true

或者您也可以使用NSDateFormatter来完成这个任务:
extension NSDate {
    struct Date {
        static let formatterYYYYMMDD: NSDateFormatter = {
            let formatter = NSDateFormatter()
            formatter.dateFormat = "yyyyMMdd"
            return formatter
        }()
    }
    var yearMonthDay: String {
        return Date.formatterYYYYMMDD.stringFromDate(self)
    }
    func isSameDayAs(date:NSDate) -> Bool {
        return yearMonthDay == date.yearMonthDay
    }
}

let date1 = NSDate()
let date2 = NSDate(timeIntervalSinceNow: 120)
print(date1.yearMonthDay == date2.yearMonthDay)   // true

print(date1.isSameDayAs(date2))    // true

另一种选择(适用于iOS8+)是使用日历方法isDate(inSameDayAsDate :):
extension NSDate {
    struct Calendar {
        static let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    }
    func isInSameDayAs(date date: NSDate) -> Bool {
        return Calendar.gregorian.isDate(self, inSameDayAsDate: date)
    }
}
let date1 = NSDate()
let date2 = NSDate(timeIntervalSinceNow: 120)
if date1.isInSameDayAs(date: date2 ){
    print(true)   // true
} else {
    print(false)
}

4

Swift 3

        let order = NSCalendar.current.compare(date1, to: date2, toGranularity: .day)

        if order == .orderedAscending { 
          // date 1 is older
        }
        else if order == .orderedDescending { 
          // date 1 is newer
        }
        else if order == .orderedSame { 
          // same day/hour depending on granularity parameter
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接