Objective c 如何检查NSDate是否发生在其他两个NSDate之间

Objective c 如何检查NSDate是否发生在其他两个NSDate之间,objective-c,cocoa,cocoa-touch,datetime,nsdate,Objective C,Cocoa,Cocoa Touch,Datetime,Nsdate,我正在尝试使用NSDate确定当前日期是否在日期范围内 例如,您可以使用NSDate获取当前日期/时间: NSDate rightNow = [NSDate date]; 然后,我想使用该日期检查它是否在9AM-5PM的范围内。如果您想知道当前日期是否在两个给定时间点之间(2009年7月1日上午9点到下午5点),请使用NSCalendar和NSDateComponents为所需时间构建NSDate实例,并将它们与当前日期进行比较 如果您想知道当前日期是否在每天这两个小时之间,那么您可能会选择另

我正在尝试使用NSDate确定当前日期是否在日期范围内

例如,您可以使用NSDate获取当前日期/时间:

NSDate rightNow = [NSDate date];

然后,我想使用该日期检查它是否在9AM-5PM

的范围内。如果您想知道当前日期是否在两个给定时间点之间(2009年7月1日上午9点到下午5点),请使用NSCalendar和NSDateComponents为所需时间构建NSDate实例,并将它们与当前日期进行比较


如果您想知道当前日期是否在每天这两个小时之间,那么您可能会选择另一种方式。使用和NSCalendar以及您的NSDate创建一个NSDateComponents对象,并比较小时组件。

我想出了一个解决方案。如果您有更好的解决方案,请随意离开,我会将其标记为正确

+ (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(或否、nil等),运算符
&
&
>“短路”,而
|
|
如果第一个参数是而不是0,则执行相同的操作。如果
date
beginDate
之前,测试返回
NO
,甚至不需要与
endDate
进行比较。基本上,它与您的代码做相同的事情,但是在一行的单个语句中,而不是5(或7,带空格)


这是一种建设性的输入,因为当程序员理解他们特定的编程语言计算逻辑表达式的方式时,他们可以更有效地构建逻辑表达式,而不必考虑太多效率问题。然而,也有类似的测试效率较低,因为并非所有操作员都短路。(事实上,大多数不能短路,例如数字比较运算符。)当有疑问时,明确地分解逻辑总是安全的,但是当您让语言/编译器为您处理一些小事情时,代码的可读性会更高。

这可以通过使用日期的时间间隔轻松完成,如下所示:

const NSTimeInterval i = [date timeIntervalSinceReferenceDate];
return ([startDate timeIntervalSinceReferenceDate] <= i &&
        [endDate timeIntervalSinceReferenceDate] >= i);
const NSTimeInterval i=[date-timeintervalncereferencedate];
返回([startDate TimeIntervalenceReferenceDate]=i);

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
    }
}
@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
    }
}

继续使用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:)

Swift中更好的版本:

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
    }
}
@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
    }
}

如果可以将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)
然后,使用
DateInterval
contains
方法检查日期是否在间隔内:

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

对于这个问题有更好更快的解决方案

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,您可以使用以下两种解决方案之一来检查日期是否出现在其他两个日期之间


#1.使用
DateInterval
包含(:)
方法
DateInterval
有一个名为的方法<代码>包含(:)具有以下声明:

func contains(_ date: Date) -> Bool
func contains(_ element: Bound) -> Bool
指示此间隔是否包含给定日期

以下代码显示了如何使用
包含(:)
来检查日期是否出现在其他两个日期之间:

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
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

#2.使用
ClosedRange
包含(:)
方法
ClosedRange
有一个名为的方法<代码>包含(:)具有以下声明:

func contains(_ date: Date) -> Bool
func contains(_ element: Bound) -> Bool
返回一个布尔值,指示给定元素是否包含在范围内

以下代码显示了如何使用
包含(:)
来检查日期是否出现在其他两个日期之间:

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
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

这看起来不错,但您可能希望将其重命名为这样的名称:+(BOOL)date:(NSDate*)date介于date:(NSDate*)beginDate和date:(NSDate*)endDate之间,以避免混淆。代码:golf!编译器应该缩短比较,使效率大致等于您所拥有的:return([date compare:beginDate]!=sensorderedescending)&([date compare:endDate]!=sensorderedescending));更好的是,我将它作为一个实例方法(NSDate的补充),而不是类方法。我要说的是:-介于日期和日期之间:太好了!我根据这个分类:
-(BOOL)介于date:(NSDate*)beginDate和date:(NSDate*)endDate之间很好的解决方案,您甚至可以通过短路(和一个基本的De Morgan应用程序)
return!([date compare:startDate]==sensorderedascing | |[date compare:endDate]==sensorderedescing)
可以理解。我不知道Objective-C会使评估短路。我相信你的话。谢谢你帮我澄清。我想我会认为你是正确的,因为你的答案比我自己的更简洁……我学到了一些东西:)不必相信我的话——我提倡这个原则“信任,但要验证”(谢谢,罗纳德·里根!)如果