【问题标题】:NSDate Comparison using Swift使用 Swift 进行 NSDate 比较
【发布时间】:2014-11-29 16:01:30
【问题描述】:

我正在开发一个需要检查作业截止日期的应用程序。我想知道截止日期是否在下周内,如果是,则执行操作。
我能找到的大部分文档都在 Objective-C 中,我不知道如何在 Swift 中做到这一点。 感谢您的帮助!

【问题讨论】:

标签: swift nsdate xcode6


【解决方案1】:

如果您想支持==<><=>= 支持NSDates,您只需在某处声明即可:

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

【讨论】:

  • @Isuru ComparableEquatable 协议的后代,因此您不需要声明两者都符合。
  • 只是好奇为什么它不是默认内置的?!
  • @dVaffection 在 Objective-C 中(声明了 NSDate 和朋友),如果您使用 ==&lt;&gt; 等进行比较,您将得到以下结果比较它们在内存中的地址,而不是比较它们的实际值。在 Swift 中,它们仍然被视为引用,因此我认为选择是 (1) 保持在 ObjC 中的逐指针比较,或者 (2) 通过不提供比较实现来消除混淆。
  • 这种方法的另一个好处是 Array.maxElement() 等随后可自动用于 NSDates 数组。
  • @MarcioCruz 这只是 Swift 的一个要求,即所有运算符的实现都应该在全局范围内。请参阅此处的讨论:stackoverflow.com/questions/35246003/…
【解决方案2】:

我喜欢使用扩展来使代码更具可读性。这里有一些 NSDate 扩展,可以帮助你清理代码并使其易于理解。我把它放在一个 sharedCode.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...
}

【讨论】:

  • 你应该简化你的代码。 return self.compare(dateToCompare) == NSComparisonResult.OrderedDescending
  • isEqualToDate 也由 Apple 提供。它的声明与 Apple 定义的声明冲突。
  • 不是每天都有24小时
  • 这个答案很糟糕,永远不应该被接受。不要永远在您创建的日期中添加时间间隔。这正是NSDateComponents 存在的原因。有很多边缘情况没有得到正确处理,不添加对ComparableNSDate 的一致性是没有意义的。我建议使用John's solution
  • 更好的解决方案是让 NSDate Equatable、Comparable,然后你可以简单地做date1 &lt; date2
【解决方案3】:

这是你在 Swift 中比较两个 NSDates 的方式,我刚刚在 Xcode 的 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");
}

所以要检查日期 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)");
}

【讨论】:

  • 按顺序降序表示 date1 > date2?
  • 是的,@Henryoscannlain-miller。
【解决方案4】:

我总是在一行中做到这一点:

let greater = date1.timeIntervalSince1970 < date2.timeIntervalSince1970

if 块中仍然可读

【讨论】:

    【解决方案5】:

    在 Swift3 中,Foundation 中的 Date 结构现在实现了 Comparable 协议。因此,之前的 Swift2 NSDate 方法被 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
    }
    

    注意...

    在 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`.
    

    【讨论】:

      【解决方案6】:
      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
          }
      }
      

      【讨论】:

        【解决方案7】:

        如果您想在 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
         }
        }
        

        对于其他日历比较,将 .day 更改为;

        .年 。月 。日 。小时 。分钟 .秒

        【讨论】:

          【解决方案8】:

          Swift 已经实现了日期比较,只需使用 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)
          

          【讨论】:

            【解决方案9】:

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

            【讨论】:

              【解决方案10】:

              这个函数对我有用,用于比较一个日期 (startDate) 是否在 endDate 之后,并且两者都被定义为 NSDate 变量:

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

              【讨论】:

                【解决方案11】:

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

                【讨论】:

                  【解决方案12】:
                  var dateFormatter = NSDateFormatter()
                  dateFormatter.dateFormat = "yyyy-MM-dd"
                  let dateData: String = dateFormatter.stringFromDate(date1)
                  let testDate: String = dateFormatter.stringFromDate(date2)
                  print(dateData == testDate)
                  

                  【讨论】:

                    【解决方案13】:
                    someArray.sort({($0.dateAdded?.timeIntervalSinceReferenceDate)! < ($1.dateAdded?.timeIntervalSinceReferenceDate)!})
                    

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

                    class MyClass {
                        let dateAdded: NSDate?
                    }
                    

                    【讨论】:

                      【解决方案14】:

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

                      使用简单的代码。

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

                      【讨论】:

                        【解决方案15】:

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

                        toGranularity 可以根据您要应用比较的约束进行更改。

                        【讨论】:

                          【解决方案16】:

                          在 SashaZ 上扩展 - Swift iOS 8 及更高版本

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

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

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

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

                          【讨论】:

                            猜你喜欢
                            • 2014-08-23
                            • 2011-01-16
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多