현재 날짜가 NSDate를 사용하여 날짜 범위에 속하는지 여부를 알아 내려고합니다.
예를 들어 NSDate를 사용하여 현재 날짜 / 시간을 가져올 수 있습니다.
NSDate rightNow = [NSDate date];
그런 다음 해당 날짜를 사용하여 오전 9시-오후 5시 범위에 있는지 확인하고 싶습니다 .
답변:
해결책을 찾았습니다. 더 나은 솔루션이 있다면 자유롭게 남겨 주시면 올바른 것으로 표시하겠습니다.
+ (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;
}
- (BOOL)isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate;
return !([date compare:startDate] == NSOrderedAscending || [date compare:endDate] == NSOrderedDescending);
첫 번째 부분에서는 @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 개)가 아닌 한 줄의 단일 명령문으로 수행됩니다.
프로그래머가 자신의 특정 프로그래밍 언어가 논리식을 평가하는 방식을 이해하면 효율성에 대한 관심없이보다 효과적으로 구성 할 수 있기 때문에 이것은 건설적인 입력으로 의도 된 것입니다. 그러나 모든 작업자가 단락되는 것은 아니기 때문에 효율성이 떨어지는 유사한 테스트 가 있습니다. (사실 대부분 은 수치 비교 연산자와 같이 단락 할 수 없습니다 .) 의심스러운 경우 논리를 분리 할 때 항상 명시 적으로 표시하는 것이 안전하지만 언어 / 컴파일러가 작은 일을 처리하도록하면 코드를 훨씬 더 쉽게 읽을 수 있습니다. 당신을 위해.
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
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입니다 :)
이 문제에 대한 더 좋고 더 빠른 해결책이 있습니다.
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 이상에서 사용할 수 있습니다.
Swift 5를 사용하면 아래 두 가지 솔루션 중 하나를 사용하여 다른 두 날짜 사이에 날짜가 발생하는지 확인할 수 있습니다.
DateInterval의 contains(_:)방법을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
ClosedRange의 contains(_:)방법을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
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
}
}