Swift 3 - So sánh các đối tượng Ngày


94

Tôi đang cập nhật ứng dụng của mình lên cú pháp Swift 3.0 (Tôi biết nó vẫn đang trong giai đoạn thử nghiệm nhưng tôi muốn chuẩn bị ngay khi nó được phát hành).

Cho đến khi bản Beta trước đó của Xcode (Beta 5) tôi đã có thể so sánh hai Dateđối tượng bằng cách sử dụng toán hạng <, >==. Nhưng trong bản beta mới nhất (Beta 6), tính năng này không hoạt động nữa. Dưới đây là một số ảnh chụp màn hình:

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Như bạn có thể thấy trong cả hai ảnh chụp màn hình, đây là hai Dateđối tượng. Nhưng tôi gặp lỗi sau: nhập mô tả hình ảnh ở đây

Tôi đang làm gì sai? Các hàm vẫn được khai báo trong Datelớp:

static func >(Date, Date)

Trả về true nếu Ngày tháng bên trái muộn hơn Ngày tháng bên tay phải.

Đây chỉ là một lỗi Beta hay tôi đang làm gì đó sai?


2
let d1 = Date() ; let d2 = Date() ; if d1 > d2 { }làm việc trong tôi Xcode 8 beta 6.
Martin R

1
Đúng. - Bạn nên tra cứu thông báo lỗi đầy đủ trong trình điều hướng Báo cáo.
Martin R

Xin cảm ơn @MartinR! Không biết rằng tôi có thể "đi sâu" vào một lỗi và lấy thêm thông tin. Đã giúp tôi rất nhiều!
beeef

chấp nhận câu trả lời đúng
Ankit Thakur

Câu trả lời:


161

Tôi đã thử đoạn mã này (trong Xcode 8 Beta 6) và nó đang hoạt động tốt.

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

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

nếu tôi muốn bỏ qua thời gian. ví dụ: 2019-05-14 12:08:14 +0000== 2019-05-14nên trả về true. rồi sao ?
Awais Fayyaz

@AwaisFayyaz Nếu bạn muốn so sánh ngày tháng mà không tính đến DateComponent. Bạn cần nhận được các thành phần bạn muốn từ ngày. Sau đó lấy ngày tháng từ DateComponents và so sánh chúng.
Giorgio Doganiero,

52

DateComparable& Equatable(kể từ Swift 3)

Câu trả lời này bổ sung cho câu trả lời của @Ankit Thakur.

Kể từ Swift 3, Datecấu trúc (dựa trên NSDatelớp bên dưới ) sử dụng các giao thức ComparableEquatable.

  • Comparableđòi hỏi rằng Datethực hiện các nhà khai thác: <, <=, >, >=.
  • Equatableyêu cầu nhà điều hành Datetriển ==khai.
  • Equatablecho phép Datesử dụng việc triển khai mặc định của !=toán tử (là nghịch đảo của việc Equatable ==triển khai toán tử).

Đoạn mã mẫu sau đây thực hành các toán tử so sánh này và xác nhận các phép so sánh nào là đúng với các printcâu lệnh.

Chức năng so sánh

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

Sử dụng mẫu

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

31

từ Swift 3 trở lên, Ngày có thể so sánh được nên chúng ta có thể so sánh trực tiếp các ngày như

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)

Ngoài ra, chúng tôi có thể tạo tiện ích mở rộng vào Ngày

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

Sử dụng: let isEqual = date1.isEqualTo(date2)


nếu tôi muốn bỏ qua thời gian. ví dụ: 2019-05-14 12:08:14 +0000== 2019-05-14nên trả về true. rồi sao ?
Awais Fayyaz

15

Nhìn này http://iswift.org/cookbook/compare-2-dates

Nhận ngày:

// Get current date
let dateA = NSDate()

// Get a later date (after a couple of milliseconds)
let dateB = NSDate()

Sử dụng câu lệnh SWITCH

// Compare them
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")
}

sử dụng câu lệnh IF

 if dateA.compare(dateB) == .orderedAscending {
     datePickerTo.date = datePicker.date
 }

 //OR

 if case .orderedAcending = dateA.compare(dateB) {

 }

9

Đối với tôi, vấn đề là tôi đã có phần mở rộng của riêng mình cho lớp Date đang xác định tất cả các toán tử so sánh. Bây giờ (kể từ swift 3) Ngày có thể so sánh được, những phần mở rộng này không cần thiết. Vì vậy, tôi đã bình luận chúng ra và nó hoạt động.


7

SWIFT 3: Không biết đây có phải là thứ bạn đang tìm kiếm hay không. Nhưng tôi so sánh một chuỗi với dấu thời gian hiện tại để xem liệu chuỗi của tôi có cũ hơn bây giờ hay không.

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

Để dùng nó:

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

5

Để so sánh ngày chỉ với năm - tháng - ngày và không có thời gian, tôi đã làm như thế này:

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

5

Nếu bạn muốn bỏ qua giây chẳng hạn, bạn có thể sử dụng

func isDate (Date, bằngTo: Date, toUnitGranularity: NSCalendar.Unit) -> Bool

Ví dụ so sánh nếu đó là cùng một ngày:

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

1

Tính đến thời điểm viết bài này, Swift hỗ trợ natively so sánh Ngày với tất cả các toán tử so sánh (ví dụ <, <=, ==, >=, và >). Bạn cũng có thể so sánh Ngày bắt buộc nhưng được giới hạn <, ==>. Nếu bạn cần so sánh hai ngày tùy chọn bằng cách sử dụng <=hoặc >=, tức là

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

Bạn có thể quá tải toán tử <=>=để hỗ trợ các tùy chọn:

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
}

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

1

Một cách khác để làm điều đó:

    switch date1.compare(date2) {
        case .orderedAscending:
            break

        case .orderedDescending:
            break;

        case .orderedSame:
            break
    }

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

1

Swift 5:

1) Nếu bạn sử dụng loại Ngày:

let firstDate  = Date()
let secondDate = Date()

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

2) Nếu bạn sử dụng loại Chuỗi:

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 

Tôi không chắc hoặc tùy chọn thứ hai hoạt động ở mức 100%. Nhưng tôi sẽ không thay đổi giá trị của firstStringDate và secondStringDate đến mức nào thì kết quả là đúng.


1

trong Swift 3,4 bạn nên sử dụng "So sánh". ví dụ:

DateArray.sort { (($0)?.compare($1))! == .orderedDescending }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.