Swift 3 - การเปรียบเทียบวัตถุวันที่


99

ฉันกำลังอัปเดตแอปของฉันเป็นไวยากรณ์ Swift 3.0 (ฉันรู้ว่ามันยังอยู่ในเบต้า แต่ฉันต้องการเตรียมพร้อมทันทีที่เปิดตัว)

จนกระทั่งเบต้าก่อนหน้าของ Xcode (Beta 5) ผมสามารถที่จะเปรียบเทียบสองDateวัตถุที่ใช้ถูกดำเนิน<, และ> ==แต่ในเบต้าล่าสุด (เบต้า 6) จะไม่ทำงานอีกต่อไป นี่คือภาพหน้าจอบางส่วน:

ป้อนคำอธิบายภาพที่นี่ ป้อนคำอธิบายภาพที่นี่

ดังที่คุณเห็นในภาพหน้าจอทั้งสองสิ่งนี้เป็นDateวัตถุสองชิ้น แต่ฉันได้รับข้อผิดพลาดต่อไปนี้: ป้อนคำอธิบายภาพที่นี่

ผมทำอะไรผิดหรือเปล่า? ฟังก์ชันยังคงประกาศอยู่ในDateคลาส:

static func >(Date, Date)

ส่งคืนค่าจริงหากวันที่ทางซ้ายมือช้ากว่าวันที่ทางขวามือ

นี่เป็นเพียงข้อผิดพลาดของเบต้าหรือฉันทำอะไรผิด?


2
let d1 = Date() ; let d2 = Date() ; if d1 > d2 { }ทำงานใน Xcode 8 beta 6 ของฉัน
Martin R

1
ใช่. - คุณควรค้นหาข้อความแสดงข้อผิดพลาดทั้งหมดในตัวนำทางรายงาน
Martin R

ขอบคุณ @MartinR! ไม่รู้ว่าฉันสามารถ "ดำดิ่ง" สู่ข้อผิดพลาดและรับข้อมูลเพิ่มเติมได้ ช่วยฉันได้มาก!
beeef

ยอมรับคำตอบที่ถูกต้อง
Ankit Thakur

คำตอบ:


167

ฉันได้ลองใช้ตัวอย่างข้อมูลนี้แล้ว (ใน 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ควรคืนค่าจริง แล้วไง ?
Awais Fayyaz

@AwaisFayyaz หากคุณต้องการเปรียบเทียบวันที่โดยไม่ต้องคำนึงถึง DateComponent คุณต้องได้รับส่วนประกอบที่คุณต้องการตั้งแต่วันที่ จากนั้นรับวันที่จาก DateComponents และเปรียบเทียบ
Giorgio Doganiero

53

Dateเป็นComparable& Equatable(ณ Swift 3)

คำตอบนี้เติมเต็มคำตอบของ @Ankit Thakur

เนื่องจาก Swift 3 โครงสร้างDate(ขึ้นอยู่กับNSDateคลาสพื้นฐาน) จึงใช้ComparableและEquatableโปรโตคอล

  • Comparableต้องการให้Dateดำเนินการผู้ประกอบการ: <, <=, ,>>=
  • 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

32

จาก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)

อีกทางหนึ่งเราสามารถสร้างส่วนขยายในวันที่

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ควรคืนค่าจริง แล้วไง ?
Awais Fayyaz

17

ดูhttp://iswift.org/cookbook/compare-2-datesนี้

รับวันที่:

// Get current date
let dateA = NSDate()

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

การใช้คำสั่ง 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")
}

โดยใช้คำสั่ง IF

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

 //OR

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

 }

9

สำหรับฉันปัญหาคือฉันมีส่วนขยายของตัวเองไปยังคลาส Date ที่กำหนดตัวดำเนินการเปรียบเทียบทั้งหมด ตอนนี้ (ตั้งแต่ swift 3) ที่เทียบเคียงวันที่แล้วไม่จำเป็นต้องใช้ส่วนขยายเหล่านี้ ดังนั้นฉันจึงแสดงความคิดเห็นและมันได้ผล


8

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
}

6

หากคุณต้องการละเว้นวินาทีเช่นคุณสามารถใช้ได้

func isDate (วันที่, วันที่เท่ากัน, วันที่, ไปยังUnitGranularity: NSCalendar.Unit) -> บูล

ตัวอย่างเปรียบเทียบว่าเป็นวันเดียวกันหรือไม่:

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

5

ในการเปรียบเทียบวันที่เฉพาะกับปี - เดือน - วันและไม่มีเวลาสำหรับฉันทำงานเช่นนี้

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

1

เป็นเวลาของการเขียนนี้สวิฟท์สนับสนุนโดยกำเนิดเมื่อเทียบกับผู้ประกอบการวันที่เปรียบเทียบทั้งหมด (เช่น<, <=, ==, >=และ>) นอกจากนี้คุณยังสามารถเปรียบเทียบวันที่ไม่จำเป็น แต่จะถูก จำกัด ให้<, และ== >หากคุณต้องการเปรียบเทียบวันที่สองทางเลือกโดยใช้<=หรือ>=กล่าวคือ

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

คุณสามารถโอเวอร์โหลดตัวดำเนินการ<=และ>=เพื่อรองรับตัวเลือก:

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

อีกวิธีในการทำ:

    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

สวิฟต์ 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 เท่าไหร่ผลลัพธ์ก็ถูกต้อง


1

ใน Swift 3,4 คุณควรใช้ "เปรียบเทียบ" ตัวอย่างเช่น:

DateArray.sort { (($0)?.compare($1))! == .orderedDescending }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.