Swift를 사용한 NSDate 비교


153

숙제 마감일을 확인해야하는 앱을 개발 중입니다. 기한이 다음 주 이내인지 알고 싶습니다. 그런 다음 조치를 취합니다.
내가 찾을 수있는 대부분의 문서는 Objective-C에 있으며 Swift에서 수행하는 방법을 알 수 없습니다. 도와 주셔서 감사합니다!!


2
swift에는 Objective C NSDate 클래스를 사용하는 날짜 클래스가 없으므로 올바른 문서를 찾았습니다
mmmmmm

시간 구성 요소없이 NSDates 비교 중복 가능성이 있습니다. 아주 좋은 답변이 많이 있습니다.
jww


2
Swift 3에는 Date클래스가 있습니다. 에 브리지 NSDate되지만이라고 Date합니다.
BallpointBen

답변:


190

나는 코드를 더 읽기 쉽게하기 위해 확장을 사용하는 것을 좋아합니다. 다음은 코드를 정리하고 이해하기 쉽게 만드는 몇 가지 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...
}

28
코드를 단순화해야합니다. return self.compare(dateToCompare) == NSComparisonResult.OrderedDescending
Olav Gausaker 2015

5
isEqualToDate는 Apple에서도 제공합니다. Apple에서 정의한 선언과 충돌합니다.
Shamas S

4
매일 24 시간이 없습니다
Leo Dabus 2015 년

9
이 대답은 끔찍하며 절대 받아 들여서는 안됩니다. 하지 마십시오 이제까지 당신에 의해 생성 된 날짜에 시간 간격을 추가합니다. 그것이 바로 NSDateComponents존재하는 이유 입니다. 이 적절하게 핸들을있는하지 않는 가장자리의 경우 많이 있습니다 그것은 준수를 추가하지 아무 의미 ComparableNSDate. John의 솔루션을 사용하는 것이 좋습니다 .
fpg1503

3
더 나은 솔루션이있는 NSDate Equatable을 만드는 것입니다, 필적, 당신은 간단하게 할 수있는date1 < date2
aryaxt

209

지원하려는 경우 ==, <, >, <=, 또는 >=위해 NSDate의, 당신은이 곳을 선언해야합니다 :

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 ComparableEquatable프로토콜 의 자손 이므로 둘 다에 대한 적합성을 선언 할 필요가 없습니다.
John Estropia

2
왜 기본적으로 내장되어 있지 않은지 궁금하십니까?!
dVaffection 2015

3
사용 비교하면 (있는 NSDate과 친구가 선언 된) 목표 - C에서 @dVaffection는, ==, <, >, 등, 당신은 메모리에 자신의 주소, 실제 값이 아닌 비교의 비교 결과를 얻는됩니다. Swift에서는 여전히 참조로 취급되므로 (1) ObjC에있는 것처럼 포인터에 의한 비교를 유지하거나 (2) 비교를위한 구현을 제공하지 않음으로써 혼란을 제거하는 것이 선택되었다고 생각합니다.
John Estropia

2
이 접근 방식의 추가 이점은 Array.maxElement()등이 NSDates 어레이에서 자동으로 사용 가능하다는 것입니다.
pr1001

1
@MarcioCruz 모든 운영자 구현이 전역 범위에 있어야한다는 Swift 요구 사항입니다. 여기에 설명을 참조하십시오 : stackoverflow.com/questions/35246003/...
존 내사시

54

이것이 Swift에서 두 개의 NSDates를 비교하는 방법입니다. 방금 Xcode의 플레이 그라운드에서 테스트했습니다.

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

2
내림차순은 date1> date2를 의미합니까?
Henry oscannlain-miller 2014-10-05

1
네, @ Henryoscannlain-miller.
실행 취소

47

나는 항상 한 줄로했다.

let greater = date1.timeIntervalSince1970 < date2.timeIntervalSince1970

if블록 에서 여전히 읽을 수 있음


12

Swift3에서의 Date구조체는 Foundation이제 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에서 Dateis structvalue type. NSDate이다 class, 그것은이다 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

신속한 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를 다음으로 변경하십시오.

. 년. 월. 일. 시간. 분. 초


5

Swift는 이미 Date 비교를 구현하고 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)

4

Swift 3에서 Date는 Comparable이므로 다음과 같이 날짜를 직접 비교할 수 있습니다.

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

extensionDate에 만드는 더 좋은 방법

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)


3

이 함수는 하나의 날짜 (startDate)가 둘 다 NSDate 변수로 정의 된 endDate 이후인지 비교하는 데 효과적이었습니다.

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

2

구현 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)!})

dateAdded는 내 개체의 NSDate 변수입니다.

class MyClass {
    let dateAdded: NSDate?
}

1

현재 시간 거짓말을 2 회 (날짜 2 회) 확인하는 시나리오가 있는데, 예를 들어 클리닉 (병원) 개원 시간과 폐점 시간 사이의 현재 거짓말을 확인하고 싶습니다.

간단한 코드를 사용하십시오.

      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

신속한 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는 비교를 적용하려는 제약 조건에 따라 변경할 수 있습니다.


1

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)) }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.