我试图弄清楚当前日期是否在使用 NSDate 的日期范围内。
例如,您可以使用 NSDate 获取当前日期/时间:
NSDate rightNow = [NSDate date];
然后我想用那个日期来检查它是否在9AM - 5PM的范围内。
我试图弄清楚当前日期是否在使用 NSDate 的日期范围内。
例如,您可以使用 NSDate 获取当前日期/时间:
NSDate rightNow = [NSDate date];
然后我想用那个日期来检查它是否在9AM - 5PM的范围内。
我想出了一个解决方案。如果您有更好的解决方案,请随时留下,我会将其标记为正确。
+ (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;
}
对于第一部分,使用来自@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,带空格)。
这旨在作为建设性的输入,因为当程序员了解他们的特定编程语言评估逻辑表达式的方式时,他们可以更有效地构造它们而无需过多考虑效率。但是,也有类似的测试效率较低,因为并非所有运算符都会短路。(事实上,大多数都不能短路,比如数值比较运算符。)如果有疑问,明确地分解逻辑总是安全的,但是当你让语言/编译器处理小事情时,代码的可读性会更高为你。
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
}
}
如果您想知道当前日期是否在两个给定时间点之间(2009 年 7 月 1 日上午 9 点至下午 5 点),请使用 NSCalendar 和 NSDateComponents 为所需时间构建 NSDate 实例并将它们与当前日期进行比较。
如果您想知道当前日期是否在每天这两个小时之间,那么您可能会走另一条路。使用 NSCalendar 和您的 NSDate 创建一个 NSDateComponents 对象并比较小时组件。
继续使用 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 :)
如果您可以针对 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
这可以使用日期的时间间隔轻松完成,如下所示:
const NSTimeInterval i = [date timeIntervalSinceReferenceDate];
return ([startDate timeIntervalSinceReferenceDate] <= i &&
[endDate timeIntervalSinceReferenceDate] >= i);
对于这个问题,有更好更快捷的解决方案。
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)
甚至您也可以随机传递日期,因为此扩展程序会检查哪个是最小的,哪个不是。
您可以在 swift 3 及更高版本中使用它。
使用 Swift 5,您可以使用以下两种解决方案之一来检查日期是否介于其他两个日期之间。
DateInterval
'scontains(_:)
方法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
'scontains(_:)
方法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
}
}