我正在尝试使用NSDate找出当前日期是否在日期范围内。
例如,您可以使用NSDate获取当前日期/时间:
NSDate rightNow = [NSDate date];
然后,我想使用该日期检查它是否在9AM-5PM范围内。
Answers:
我想出了一个解决方案。如果您有更好的解决方案,请随时将其保留,我将其标记为正确。
+ (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等)) ,而|
并||
做相同的,如果第一个参数是不是 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当然是NSDate :)
有更好更好的解决方案。
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
指示此间隔是否包含给定日期。
以下Playground代码显示了如何使用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
返回一个布尔值,该布尔值指示给定元素是否包含在范围内。
以下Playground代码显示了如何使用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
}
}