NSDate가 다른 두 NSDate간에 발생하는지 확인하는 방법


90

현재 날짜가 NSDate를 사용하여 날짜 범위에 속하는지 여부를 알아 내려고합니다.

예를 들어 NSDate를 사용하여 현재 날짜 / 시간을 가져올 수 있습니다.

NSDate rightNow = [NSDate date];

그런 다음 해당 날짜를 사용하여 오전 9시-오후 5시 범위에 있는지 확인하고 싶습니다 .


1
당신에 대한 답변을 살펴 걸릴 수 있습니다 이 질문에 오후 5시에서 오후 9시까지로,있는 NSDate는 특정 기간에 대한 객체를 만드는 방법에 대한 자세한 내용은 예를.
Marc Charbonneau

답변:


167

해결책을 찾았습니다. 더 나은 솔루션이 있다면 자유롭게 남겨 주시면 올바른 것으로 표시하겠습니다.

+ (BOOL)date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate
{
    if ([date compare:beginDate] == NSOrderedAscending)
        return NO;

    if ([date compare:endDate] == NSOrderedDescending) 
        return NO;

    return YES;
}

3
괜찮아 보이지만 혼동을 피하기 위해 + (BOOL) date : (NSDate *) date isBetweenDate : (NSDate *) beginDate andDate : (NSDate *) endDate와 같이 이름을 바꿀 수 있습니다.
Jeff Kelley

3
코드 골프! 컴파일러는 비교를 단락시켜 효율성을 사용자가 가진 것과 거의 동일하게 만들어야합니다. return (([date compare : beginDate]! = NSOrderedDescending) && ([date compare : endDate]! = NSOrderedAscending));
Tim

1
더 좋은 점은 이것을 클래스 메서드가 아닌 인스턴스 메서드 (NSDate에 추가)로 만드는 것입니다. 나는 이것으로 갈 것이다 : -isBetweenDate : andDate :
Dave Batton

4
우수한! :이에서 범주를 만든- (BOOL)isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate;
마테오 Alessani

2
좋은 솔루션은, 당신도 단락 (그리고 기본 드 모건 응용 프로그램에서 덜 장황 그것을 만들 수 있습니다.return !([date compare:startDate] == NSOrderedAscending || [date compare:endDate] == NSOrderedDescending);
가브리엘 Petronella에게

13

첫 번째 부분에서는 @kperryua 의 답변을 사용하여 비교할 NSDate 개체를 구성합니다. 당신 자신의 질문에 대한 당신의 대답에서, 당신이 알아 낸 것 같습니다.

실제로 날짜를 비교하기 위해 귀하의 답변에 대한 @Tim 의 의견에 전적으로 동의합니다 . 더 간결하지만 실제로는 코드와 정확히 일치하며 그 이유를 설명하겠습니다.

+ (BOOL) date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
    return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending));
}

return 문이 && 연산자의 두 피연산자를 모두 평가해야하는 것처럼 보일 수 있지만 실제로는 그렇지 않습니다. 핵심은 " 단락 평가 "로, 다양한 프로그래밍 언어로 구현되며 확실히 C로 구현됩니다. 기본적으로 연산자 &&&첫 번째 인수가 0 (또는 NO, nil 등) 인 경우 "단락"입니다. , while |||첫 번째 인수가 0 이 아닌 경우 동일한 작업을 수행합니다. date앞에 오면와 비교할 필요없이 beginDate테스트가 반환 NO됩니다 endDate. 기본적으로 코드와 동일한 작업을 수행하지만 5 개 (또는 공백이있는 7 개)가 아닌 한 줄의 단일 명령문으로 수행됩니다.

프로그래머가 자신의 특정 프로그래밍 언어가 논리식을 평가하는 방식을 이해하면 효율성에 대한 관심없이보다 효과적으로 구성 할 수 있기 때문에 이것은 건설적인 입력으로 의도 된 것입니다. 그러나 모든 작업자가 단락되는 것은 아니기 때문에 효율성이 떨어지는 유사한 테스트 있습니다. (사실 대부분 수치 비교 연산자와 같이 단락 할 수 없습니다 .) 의심스러운 경우 논리를 분리 할 때 항상 명시 적으로 표시하는 것이 안전하지만 언어 / 컴파일러가 작은 일을 처리하도록하면 코드를 훨씬 더 쉽게 읽을 수 있습니다. 당신을 위해.


1
이해할 수 있는. Objective-C가 평가를 단락시킬 것이라고는 전혀 몰랐습니다. 나는 그것에 대해 당신의 말을 받아 들일 것입니다. 정리 해주셔서 감사합니다. 나는 당신의 대답은 내 자신보다 더 간결이기 때문에 나는 올바른로 당신을 표시합니다 가정 ... 그리고 내가 뭔가 :) 배운
브록 울프

내 말을 받아 들일 필요가 없습니다. 나는 호기심을 충족시키고 무언가가 작동하고 작동하지 않을 때의 경계를 배우기 위해서만 "신뢰하지만 검증"이라는 원칙을 옹호합니다 (고마워요, 로널드 레이건!). 호출시 반환되는 내용을 기록하는 두 가지 메서드의 &&를 수행하여 확인할 수 있습니다. 첫 번째 항목이 0을 반환하면 두 번째 항목이 호출되지 않음을 알 수 있습니다.
Quinn Taylor

7

Swift의 Brock Woolf 버전 :

extension NSDate
{
    func isBetweenDates(beginDate: NSDate, endDate: NSDate) -> Bool
    {
        if self.compare(beginDate) == .OrderedAscending
        {
            return false
        }

        if self.compare(endDate) == .OrderedDescending
        {
            return false
        }

        return true
    }
}

4

현재 날짜가 주어진 두 시점 (2009 년 7 월 1 일 오전 9시-오후 5시) 사이에 속하는지 알고 싶다면 NSCalendar 및 NSDateComponents를 사용하여 원하는 시간에 NSDate 인스턴스를 빌드하고 현재 날짜와 비교합니다.

현재 날짜가 매일 이 두 시간 사이에 속하는지 알고 싶다면 다른 길로 갈 수 있습니다. NSCalendar 및 NSDate를 사용하여 NSDateComponents 개체를 만들고 시간 구성 요소를 비교합니다.


4

iOS 10.0 + / macOS 10.12+를 대상으로 할 수있는 경우 DateInterval클래스 를 사용하십시오 .

먼저 시작 및 종료 날짜로 날짜 간격을 만듭니다.

let start: Date = Date()
let middle: Date = Date()
let end: Date = Date()

let dateInterval: DateInterval = DateInterval(start: start, end: end)

그런 다음 다음 contains방법을 사용하여 날짜가 간격 내에 있는지 확인하십시오 DateInterval.

let dateIsInInterval: Bool = dateInterval.contains(middle) // true

3

다음과 같이 날짜의 시간 간격을 사용하여 쉽게 수행 할 수 있습니다.

const NSTimeInterval i = [date timeIntervalSinceReferenceDate];
return ([startDate timeIntervalSinceReferenceDate] <= i &&
        [endDate timeIntervalSinceReferenceDate] >= i);

3

Quinn과 Brock의 솔루션을 계속 사용하면 NSDate 구현을 하위 클래스로 만드는 것이 매우 좋으므로 다음과 같이 모든 곳에서 사용할 수 있습니다.

-(BOOL) isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
    return (([self compare:beginDate] != NSOrderedAscending) && ([self compare:endDate] != NSOrderedDescending));
}

그리고 코드의 어느 부분에서든 다음과 같이 사용할 수 있습니다.

[myNSDate isBetweenDate:thisNSDate andDate:thatNSDate];

(myNSDate, thisNSDate 및 thatNSDate는 물론 NSDates입니다 :)


3

이 문제에 대한 더 좋고 더 빠른 해결책이 있습니다.

extention Date {
    func isBetween(from startDate: Date,to endDate: Date) -> Bool {
        let result = (min(startDate, endDate) ... max(startDate, endDate)).contains(self)
        return result
    }
}

그러면 이렇게 부를 수 있습니다.

todayDate.isBetween(from: startDate, to: endDate)

이 확장은 어떤 것이 최소인지 아닌지 확인하기 때문에 날짜를 무작위로 전달할 수도 있습니다.

신속한 3 이상에서 사용할 수 있습니다.


2

Swift 5를 사용하면 아래 두 가지 솔루션 중 하나를 사용하여 다른 두 날짜 사이에 날짜가 발생하는지 확인할 수 있습니다.


#1. 사용 DateIntervalcontains(_:)방법을

DateInterval라는 메서드가 contains(_:)있습니다. contains(_:)다음과 같은 선언이 있습니다.

func contains(_ date: Date) -> Bool

이 간격에 지정된 날짜가 포함되는지 여부를 나타냅니다.

다음 플레이 그라운드 코드는 contains(_:)다른 두 날짜 사이에 날짜가 발생하는지 확인하기 위해 사용하는 방법을 보여줍니다 .

import Foundation

let calendar = Calendar.current
let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!
let myDate = calendar.date(from: DateComponents(year: 2012, month: 8, day: 15))!

let dateInterval = DateInterval(start: startDate, end: endDate)
let result = dateInterval.contains(myDate)
print(result) // prints: true

# 2. 사용 ClosedRangecontains(_:)방법을

ClosedRange라는 메서드가 contains(_:)있습니다. contains(_:)다음과 같은 선언이 있습니다.

func contains(_ element: Bound) -> Bool

주어진 요소가 범위 내에 포함되어 있는지 여부를 나타내는 부울 값을 반환합니다.

다음 플레이 그라운드 코드는 contains(_:)다른 두 날짜 사이에 날짜가 발생하는지 확인하기 위해 사용하는 방법을 보여줍니다 .

import Foundation

let calendar = Calendar.current
let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!
let myDate = calendar.date(from: DateComponents(year: 2012, month: 8, day: 15))!

let range = startDate ... endDate
let result = range.contains(myDate)
//let result = range ~= myDate // also works
print(result) // prints: true

-1

Swift의 더 나은 버전 :

@objc public class DateRange: NSObject {
    let startDate: Date
    let endDate: Date

    init(startDate: Date, endDate: Date) {
        self.startDate = startDate
        self.endDate = endDate
    }

    @objc(containsDate:)
    func contains(_ date: Date) -> Bool {
        let startDateOrder = date.compare(startDate)
        let endDateOrder = date.compare(endDate)
        let validStartDate = startDateOrder == .orderedAscending || startDateOrder == .orderedSame
        let validEndDate = endDateOrder == .orderedDescending || endDateOrder == .orderedSame
        return validStartDate && validEndDate
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.