【问题标题】:Swift 3 - Comparing Date objectsSwift 3 - 比较日期对象
【发布时间】:2016-12-25 09:25:16
【问题描述】:

我正在将我的应用程序更新为 Swift 3.0 语法(我知道它仍处于测试阶段,但我希望它一发布就做好准备)。

在 Xcode 的上一个 Beta(Beta 5)之前,我能够使用操作数 <>== 比较两个 Date 对象。但是在最新的测试版(Beta 6)中,这不再起作用了。以下是一些截图:

正如您在两个屏幕截图中看到的,这是两个 Date 对象。但我收到以下错误:

我做错了什么?这些函数仍然在Date 类中声明:

static func >(Date, Date)

如果左侧日期晚于右侧日期,则返回真。

这只是一个 Beta 错误还是我做错了什么?

【问题讨论】:

  • let d1 = Date() ; let d2 = Date() ; if d1 > d2 { } 在我的 Xcode 8 beta 6 中工作。
  • 是的。 – 您应该在报告导航器中查找完整的错误消息。
  • 谢谢@MartinR!不知道我可以“潜入”错误并获取更多信息。帮了我很多!
  • 接受正确答案

标签: ios xcode swift3 beta


【解决方案1】:

我已经尝试过这个 sn-p(在 Xcode 8 Beta 6 中),它工作正常。

let date1 = Date()
let date2 = Date().addingTimeInterval(100)

if date1 == date2 { ... }
else if date1 > date2 { ... }
else if date1 < date2 { ... }

【讨论】:

  • 如果我想忽略时间。例如2019-05-14 12:08:14 +0000 == 2019-05-14 应该返回 true。然后呢?
  • @AwaisFayyaz 如果您想比较日期而不考虑 DateComponent。您需要从日期中获取所需的组件。然后从 DateComponents 中获取日期并进行比较。
【解决方案2】:

DateComparable & Equatable(从 Swift 3 开始)

这个答案补充了@Ankit Thakur 的答案。

从 Swift 3 开始,Date 结构体(基于底层的NSDate 类)采用了ComparableEquatable 协议。

  • Comparable 要求 Date 实现运算符:&lt;&lt;=&gt;&gt;=
  • Equatable 要求 Date 实现 == 运算符。
  • Equatable 允许 Date 使用 != 运算符的默认实现(与 Equatable == 运算符实现相反)。

以下示例代码练习这些比较运算符,并使用print 语句确认哪些比较为真。

比较函数

import Foundation

func describeComparison(date1: Date, date2: Date) -> String {

    var descriptionArray: [String] = []

    if date1 < date2 {
        descriptionArray.append("date1 < date2")
    }

    if date1 <= date2 {
        descriptionArray.append("date1 <= date2")
    }

    if date1 > date2 {
        descriptionArray.append("date1 > date2")
    }

    if date1 >= date2 {
        descriptionArray.append("date1 >= date2")
    }

    if date1 == date2 {
        descriptionArray.append("date1 == date2")
    }

    if date1 != date2 {
        descriptionArray.append("date1 != date2")
    }

    return descriptionArray.joined(separator: ",  ")
}

使用示例

let now = Date()

describeComparison(date1: now, date2: now.addingTimeInterval(1))
// date1 < date2,  date1 <= date2,  date1 != date2

describeComparison(date1: now, date2: now.addingTimeInterval(-1))
// date1 > date2,  date1 >= date2,  date1 != date2

describeComparison(date1: now, date2: now)
// date1 <= date2,  date1 >= date2,  date1 == date2

【讨论】:

    【解决方案3】:

    Swift 3 及以上版本开始,日期是可比较的,所以我们可以直接比较日期,例如

    let date1 = Date()
    let date2 = Date().addingTimeInterval(50)
    
    let isGreater = date1 > date2
    print(isGreater)
    
    let isSmaller = date1 < date2
    print(isSmaller)
    
    let isEqual = date1 == date2
    print(isEqual)
    

    或者我们可以在 Date 上创建扩展

    extension Date {
    
      func isEqualTo(_ date: Date) -> Bool {
        return self == date
      }
      
      func isGreaterThan(_ date: Date) -> Bool {
         return self > date
      }
      
      func isSmallerThan(_ date: Date) -> Bool {
         return self < date
      }
    }
    

    使用: let isEqual = date1.isEqualTo(date2)

    【讨论】:

    • 如果我想忽略时间。例如2019-05-14 12:08:14 +0000 == 2019-05-14 应该返回 true。然后呢?
    【解决方案4】:

    不要使用比较器&lt;&gt;==!=
    使用compare(_ other: Date)函数。

    用法

    // Get current date
    let dateA = Date()
    
    // Get a later date (after a couple of milliseconds)
    let dateB = Date()
    
    // Compare them using switch
    switch dateA.compare(dateB) {
        case .orderedAscending     :   print("Date A is earlier than date B")
        case .orderedDescending    :   print("Date A is later than date B")
        case .orderedSame          :   print("The two dates are the same")
    }
    
    // Compare them using if
    if dateA.compare(dateB) == .orderedAscending {
        datePickerTo.date = datePicker.date
    }
    

    【讨论】:

    • ">不要使用比较器 、==、!=。" ... 为什么?
    【解决方案5】:

    对我来说,问题在于我有自己的 Date 类扩展,它定义了所有的比较运算符。现在(因为 swift 3) Date 是可比较的,不需要这些扩展。所以我把它们注释掉了,它起作用了。

    【讨论】:

      【解决方案6】:

      SWIFT 3:不知道这是否是您要找的。但是我将一个字符串与当前时间戳进行比较,看看我的字符串是否比现在更旧。

      func checkTimeStamp(date: String!) -> Bool {
              let dateFormatter: DateFormatter = DateFormatter()
              dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
              dateFormatter.locale = Locale(identifier:"en_US_POSIX")
              let datecomponents = dateFormatter.date(from: date)
      
              let now = Date()
      
              if (datecomponents! >= now) {
                  return true
              } else {
                  return false
              }
          }
      

      要使用它:

      if (checkTimeStamp(date:"2016-11-21 12:00:00") == false) {
          // Do something
      }
      

      【讨论】:

        【解决方案7】:

        例如,如果您想忽略秒数 你可以使用

        func isDate(Date, equalTo: Date, toUnitGranularity: NSCalendar.Unit) -> Bool

        如果是同一天,例如比较:

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

        【讨论】:

          【解决方案8】:

          仅将日期与年-月-日进行比较,而没有时间对我来说是这样的:

               let order = Calendar.current.compare(self.startDate, to: compareDate!, toGranularity: .day)  
          
                                switch order {
                                  case .orderedAscending:
                                      print("\(gpsDate) is after \(self.startDate)")
                                  case .orderedDescending:
                                      print("\(gpsDate) is before \(self.startDate)")
                                  default:
                                      print("\(gpsDate) is the same as \(self.startDate)")
                                  }
          

          【讨论】:

            【解决方案9】:

            截至撰写本文时,Swift 原生支持将日期与所有比较运算符(即&lt;&lt;===&gt;=&gt;)进行比较。您还可以比较可选日期,但仅限于&lt;==&gt;。如果您需要使用&lt;=&gt;= 比较两个可选日期,即

            let date1: Date? = ...
            let date2: Date? = ...
            if date1 >= date2 { ... }
            

            您可以重载 &lt;=&gt;= 运算符以支持可选操作:

            func <= <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
                return lhs == rhs || lhs < rhs
            }
            
            func >= <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
                return lhs == rhs || lhs > rhs
            }
            

            【讨论】:

              【解决方案10】:
              extension Date {
               func isBetween(_ date1: Date, and date2: Date) -> Bool {
                  return (min(date1, date2) ... max(date1, date2)).contains(self)
                }
              }
              
              let resultArray = dateArray.filter { $0.dateObj!.isBetween(startDate, and: endDate) }
              

              【讨论】:

                【解决方案11】:

                另一种方法:

                    switch date1.compare(date2) {
                        case .orderedAscending:
                            break
                
                        case .orderedDescending:
                            break;
                
                        case .orderedSame:
                            break
                    }
                

                【讨论】:

                  【解决方案12】:
                     var strDateValidate = ""
                              let dateFormatter = DateFormatter()
                              dateFormatter.dateFormat = "yyyy-MM-dd"
                  
                              let firstDate = dateFormatter.date(from:lblStartTime.text!)
                              let secondDate = dateFormatter.date(from:lblEndTime.text!)
                  
                              if firstDate?.compare(secondDate!) == .orderedSame || firstDate?.compare(secondDate!) == .orderedAscending {
                                  print("Both dates are same or first is less than scecond")
                                  strDateValidate = "yes"
                              }
                              else
                              {
                                  //second date is bigger than first
                                  strDateValidate = "no"
                              }
                  
                              if strDateValidate == "no"
                              {
                                  alertView(message: "Start date and end date for a booking must be equal or Start date must be smaller than the end date", controller: self)
                              }
                  

                  【讨论】:

                    【解决方案13】:

                    斯威夫特 5:

                    1) 如果使用日期类型:

                    let firstDate  = Date()
                    let secondDate = Date()
                    
                    print(firstDate > secondDate)  
                    print(firstDate < secondDate)
                    print(firstDate == secondDate)
                    

                    2) 如果使用字符串类型:

                    let firstStringDate  = "2019-05-22T09:56:00.1111111"
                    let secondStringDate = "2019-05-22T09:56:00.2222222"
                    
                    print(firstStringDate > secondStringDate)  // false
                    print(firstStringDate < secondStringDate)  // true
                    print(firstStringDate == secondStringDate) // false 
                    

                    我不确定,或者第二个选项可以 100% 工作。但是我不会改变 firstStringDate 和 secondStringDate 的值多少结果是正确的。

                    【讨论】:

                      【解决方案14】:

                      在 Swift 3,4 中,您应该使用“比较”。 例如:

                      DateArray.sort { (($0)?.compare($1))! == .orderedDescending }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2011-11-28
                        • 1970-01-01
                        • 2018-08-26
                        • 2023-03-29
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多