Swift kullanarak NSDate Karşılaştırması


153

Ben bir uygulama üzerinde çalışıyorum ödev için son tarihini kontrol gerektirir. Bir bitiş tarihinin gelecek hafta içinde olup olmadığını ve daha sonra bir işlem yapıp yapmadığını bilmek istiyorum.
Bulabildiğim belgelerin çoğu Objective-C'de ve bunu Swift'te nasıl yapacağımı anlayamıyorum. Yardım için teşekkürler!!


2
swift, Objective C NSDate sınıfını kullandığınız bir tarih sınıfına sahip değil - bu nedenle doğru belgeleri buldunuz
mmmmmm

NSDates'i zaman bileşeni olmadan karşılaştırmanın olası kopyası . Çok iyi cevaplar var.
jww


2
Swift 3'ün bir Datesınıfı var. Köprülenir NSDate, ama denir Date.
BallpointBen

Yanıtlar:


188

Kodu daha okunabilir hale getirmek için uzantıları kullanmayı seviyorum. Kodunuzu temizlemeye ve anlaşılmasını kolaylaştıracak birkaç NSDate uzantısı burada. Bunu bir paylaşılanCode.swift dosyasına koydum:

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

Şimdi böyle bir şey yapabilirseniz:

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

28
Kodunuzu basitleştirmelisiniz. return self.compare(dateToCompare) == NSComparisonResult.OrderedDescending
Olav Gausaker

5
isEqualToDate, Apple tarafından da sağlanır. Apple'ın tanımladığı beyan ile çelişiyor.
Shamas S - Monica'yı geri döndür

4
Her gün 24 saat yok
Leo Dabus

9
Bu cevap korkunç ve asla kabul edilmemeli. Etmeyin hiç sizin tarafınızdan oluşturulan tarihlere zaman aralıklarını ekleyin. İşte tam da bu yüzden NSDateComponentsvar. Orada düzgün kolu olmak değildir uç örnekleri bir yeri vardır ve uygunluğunu eklemek için hiçbir mantıklı Comparableiçin NSDate. John'un çözümünü kullanmanızı tavsiye ederim .
fpg1503

3
Daha iyi bir çözüm, NSDate'i Eşit, Karşılaştırılabilir yapmaktır, o zaman sadece yapabilirsindate1 < date2
aryaxt

209

Eğer desteklemek istiyorsanız ==, <, >, <=, veya >=için NSDates, sadece bu bir yere beyan etmek zorunda:

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

2
@Isuru Comparable, Equatableprotokolün torunudur, bu nedenle her ikisine de uygunluk bildirmeniz gerekmez.
John Estropia

2
Neden varsayılan olarak yerleşik olmadığını merak ediyor musunuz ?!
dVaffection

3
Kullandığınız karşılaştırın if (NSDate ve arkadaşları ilan edilir) Objective-C ise @dVaffection, ==, <, >, vb, hafızada kendi adresini, gerçek değerin değil karşılaştırma karşılaştırma sonucu almak olacak. Swift'te hala referans olarak ele alınmaktadırlar, bu yüzden seçimin (1) ObjC'deki gibi işaretçi karşılaştırmaları tutmak veya (2) karşılaştırmalar için bir uygulama sağlayarak karışıklığı ortadan kaldırmak olduğunu düşünüyorum.
John Estropia

2
Bu yaklaşımın ek bir yararı Array.maxElement(), vb. Daha sonra NSDates dizilerinin otomatik olarak kullanılabilmesidir.
pr1001

1
@MarcioCruz Bu, tüm operatör uygulamalarının küresel kapsamda olması gereken bir Swift koşulu. Buradaki tartışmaya bakın: stackoverflow.com/questions/35246003/…
John Estropia

54

Swift'teki iki NSDate'i nasıl karşılaştırıyorsunuz, Xcode'un oyun alanında test ettim:

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

Bir tarihin dueDateşu andan itibaren bir hafta içinde olup olmadığını kontrol etmek için :

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

2
Azalan azalan tarih1> tarih2 anlamına mı gelir?
Henry oscannlain-miller

1
Evet, @ Henryoscannlain-miller.
Geri al

46

Her zaman tek bir satırda yaptım:

let greater = date1.timeIntervalSince1970 < date2.timeIntervalSince1970

Hala ifblokta okunabilir


12

Swift3'te, şu andaki Dateyapı protokolü Foundationuygular Comparable. Yani, önceki Swift2 NSDateyaklaşımları Swift3 tarafından üstlenildi 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
}

Not ...

Swift3'te, Dateolduğu structanlamına gelir value type. NSDateolduğunu class, öyle 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
    }
}

6

Tarihleri ​​hızlı 3'te ayrıntı düzeyi (yalnızca aynı gün veya yıl vb.) İle karşılaştırmak istiyorsanız.

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

Diğer takvim karşılaştırmaları için .day olarak;

. yıl .ay .gün .saat. dakika .saniye


5

Swift zaten Tarih karşılaştırmasını uygular sadece date1> date2 vb.

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

4

Swift 3'te Tarih Karşılaştırılabilir, böylece tarihleri ​​doğrudan karşılaştırabiliriz

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

let isGreater = date1 > date2
print(isGreater)

let isEqual = date1 == date2
print(isEqual)

Veya alternatif olarak

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

Randevu extensioniçin daha iyi bir yol

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
  }

}

kullanım let isGreater = date1.isGreater(than: date2)


3

Bu işlev, bir tarihin (startDate), her ikisinin de NSDate değişkenleri olarak tanımlandığı endDate'ten sonra olup olmadığını karşılaştırmak için çalıştı:

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

2

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

2
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateData: String = dateFormatter.stringFromDate(date1)
let testDate: String = dateFormatter.stringFromDate(date2)
print(dateData == testDate)

1
someArray.sort({($0.dateAdded?.timeIntervalSinceReferenceDate)! < ($1.dateAdded?.timeIntervalSinceReferenceDate)!})

date Added nesnemdeki bir NSDate değişkeni

class MyClass {
    let dateAdded: NSDate?
}

1

Şimdiki zaman yalanlarını s / b'yi iki kez (iki tarih) kontrol etmek için senaryomuz var.Örneğin, klinik (Hastane) açılış zamanı ve kapanış zamanı arasındaki geçerli yalanı kontrol etmek istiyorum.

Basit Kodu kullanın.

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

1

Hızlı 3 için, iki tarih arasında karşılaştırma yapmak üzere aşağıdaki işlevi kullanabilirsiniz.

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, karşılaştırmanızı uygulamak istediğiniz kısıtlamalara göre değiştirilebilir.


1

SashaZ'yi genişletmek için

Hızlı iOS 8 ve üstü Daha büyük veya daha küçük tarih karşılaştırmalarından daha fazlasına ihtiyacınız olduğunda. Örneğin, aynı gün mü yoksa önceki gün mü ...

Not: Saat dilimini asla unutmayın. Takvim saat diliminin bir varsayılanı vardır, ancak varsayılanı beğenmezseniz, saat dilimini kendiniz ayarlamanız gerekir. Hangi gün olduğunu bilmek için hangi saat diliminde sorduğunuzu bilmeniz gerekir.

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

Şöyle kullanın:

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

Daha karmaşık bir örnek. "FindThisDay" ile aynı gün olan bir dizideki tüm tarihleri ​​bulun ve filtreleyin:

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)) }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.