使用 Swift 进行 NSDate 比较

我正在开发一个应用程序,要求检查家庭作业的截止日期。我想知道预产期是否在下周内,如果是,那么就采取行动。
我能找到的大部分文档都在 Objective-C 中,但我不知道如何在 Swift 中实现。 谢谢你的帮助! !

91964 次浏览

这是你在 Swift 中比较两个 NSDates 的方法,我刚刚在 Xcode 的操场上测试过:

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

因此,要检查 dueDate的日期是否在一周之内:

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)");
}
someArray.sort({($0.dateAdded?.timeIntervalSinceReferenceDate)! < ($1.dateAdded?.timeIntervalSinceReferenceDate)!})

DateAdd 是我的对象中的一个 NSDate 变量

class MyClass {
let dateAdded: NSDate?
}

如果你想支持 ==<><=或者 >=NSDate,你只需要在某处声明:

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

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

我喜欢使用扩展来提高代码的可读性。下面是一些 NSDate 扩展,它们可以帮助清理代码,使代码易于理解。我把它放在一个共享的 Code.swift 文件中:

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

现在,如果你能做这样的事情:

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

我总是用一句话说:

let greater = date1.timeIntervalSince1970 < date2.timeIntervalSince1970

if块中仍然可读

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

我们有场景检查当前时间线 b/w 两次(两个日期)。例如,我想检查诊所(医院)开放时间和关闭时间之间的当前位置。

使用简单的代码。

      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");
}
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateData: String = dateFormatter.stringFromDate(date1)
let testDate: String = dateFormatter.stringFromDate(date2)
print(dateData == testDate)

如果你想比较日期粒度(只是同一天或年等)在迅速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
}
}

对于其他日历比较更改

。年 。月 。一天 。小时 。分钟 。第二

在 Swift3中,Foundation中的 Date结构现在实现了 Comparable协议。因此,以前的 Swift2NSDate方法被 Swift3Date所取代。

/**
`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
}

注意..。

在 Swift3中,Datestruct,这意味着它是 value typeNSDateclass,它是 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`.

对于 Swift 3,您可以使用下面的函数来比较两个日期。

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

可以根据要应用比较的约束来更改 to粒度。

在 Swift 3中,日期是可比较的,所以我们可以直接比较日期,如

let date1 = Date()
let date2 = Date()


let isGreater = date1 > date2
print(isGreater)


let isEqual = date1 == date2
print(isEqual)

或者选择

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

更好的方法创建 extension的日期

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
}


}

使用方法 let isGreater = date1.isGreater(than: date2)

这个函数可以用来比较在 endDate 之后是否有一个日期(startDate) ,这两个日期都被定义为 NSDate 变量:

if startDate.compare(endDate as Date) == ComparisonResult.orderedDescending

Swift 已经实现了 Date 比较,只需使用 date1 > date2等等。

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

扩展到 SashaZ-Swift iOS8及以上版本

  • 这些日期是同一天的吗?
  • 这些日期是同一个月的吗?
  • 这个日期是上个月的吗?

当您需要的不仅仅是更大或更小的日期比较时。例如,它是同一天或前一天,..。

注: 永远不要忘记时区。日历时区有默认值,但是如果您不喜欢默认值,您必须自己设置时区。要知道是哪一天,你需要知道你问的是哪个时区。

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

像这样使用它:

if thisDate.compareTo(date: Date(), toGranularity: .day) == .orderedDescending {
// thisDate is a previous day
}

一个更复杂的例子。查找并筛选数组中与“ 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)) }