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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1072848/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:51:09  来源:igfitidea点击:

How to Check if an NSDate occurs between two other NSDates

objective-ccocoacocoa-touchdatetimensdate

提问by Brock Woolf

I am trying to figure out whether or not the current date falls within a date range using NSDate.

我想弄清楚当前日期是否在使用 NSDate 的日期范围内。

For example, you can get the current date/time using NSDate:

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

NSDate rightNow = [NSDate date];

I would then like to use that date to check if it is in the range of 9AM - 5PM.

然后我想使用该日期来检查它是否在上午 9 点到下午 5 点的范围内。

回答by Brock Woolf

I came up with a solution. If you have a better solution, feel free to leave it and I will mark it as correct.

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

+ (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;
}

回答by Quinn Taylor

For the first part, use the answer from @kperryuato construct the NSDate objects you want to compare with. From your answer to your own question, it sounds like you have that figured out.

对于第一部分,使用来自@kperryua的答案来构造要与之比较的 NSDate 对象。从您对自己问题的回答来看,您似乎已经明白了这一点。

For actually comparing the dates, I totally agree with @Tim's comment on your answer. It's more concise yet actually exactly equivalent to your code, and I'll explain why.

对于实际比较日期,我完全同意@Tim对您的回答的评论。它更简洁但实际上完全等同于您的代码,我将解释原因。

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

Although it may seem that the return statement must evaluate both operands of the && operator, this is actually not the case. The key is "short-circuit evaluation", which is implemented in a wide variety of programming languages, and certainly in C. Basically, the operators &and &&"short circuit" if the first argument is 0 (or NO, nil, etc.), while |and ||do the same if the first argument is not0. If datecomes before beginDate, the test returns NOwithout even needing to compare with endDate. Basically, it does the same thing as your code, but in a single statement on one line, not 5 (or 7, with whitespace).

尽管看起来 return 语句必须计算 && 运算符的两个操作数,但实际上并非如此。关键是“短路评估”,它在多种编程语言中实现,当然在 C 中也是如此。基本上,运算符&&&“短路”如果第一个参数是 0(或 NO、nil 等) , while|||如果第一个参数为 0 ,则执行相同的操作。如果date出现在 之前beginDate,则测试将返回NO,甚至无需与 进行比较endDate。基本上,它与您的代码做同样的事情,但在一行的单个语句中,而不是 5(或 7,带空格)。

This is intended as constructive input, since when programmers understand the way their particular programming language evaluates logical expressions, they can construct them more effectively without so much about efficiency. However, there are similar tests that wouldbe less efficient, since not all operators short-circuit. (Indeed, most cannotshort-circuit, such as numerical comparison operators.) When in doubt, it's always safe to be explicit in breaking apart your logic, but code can be much more readable when you let the language/compiler handle the little things for you.

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

回答by ChikabuZ

Brock Woolf version in Swift:

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

回答by Bryan Luby

If you can target iOS 10.0+/macOS 10.12+, then use the DateIntervalclass.

如果您可以针对 iOS 10.0+/macOS 10.12+,请使用DateInterval该类。

First, create a date interval with a start and end date:

首先,创建一个具有开始和结束日期的日期间隔:

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

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

Then, check if the date is in the interval by using the containsmethod of DateInterval:

然后,使用以下contains方法检查日期是否在区间内DateInterval

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

回答by kperryua

If you want to know if the current date falls between two given points in time (9AM - 5PM on 7/1/09), use NSCalendar and NSDateComponents to build NSDate instances for the desired times and compare them with the current date.

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

If you want to know if the current date falls between these two hours everyday, then you could probably go the other way. Create an NSDateComponents object with and NSCalendar and your NSDate and compare the hour components.

如果你想知道,如果当前日期这两个小时降到一天,那么你很可能走另一条路。使用 NSCalendar 和您的 NSDate 创建一个 NSDateComponents 对象并比较小时组件。

回答by justin

This can be accomplished easily using the dates' time intervals, like so:

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

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

回答by Rehan Ali

There is better and more swifty solution for this problem.

对于这个问题,有更好、更快捷的解决方案。

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

Then you can call it like this.

然后你可以这样称呼它。

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

Even you can pass date random as this extension checks which one is minimum and which one in not.

即使您可以随机传递日期,因为此扩展程序会检查哪个是最小值,哪个不是。

you can use it in swift 3 and above.

您可以在 swift 3 及更高版本中使用它。

回答by MiQUEL

Continuing with Quinn's and Brock′s solutions, is very nice to subclass NSDate implementation, so it can be used everywhere like this:

继续使用 Quinn 和 Brock 的解决方案,对 NSDate 实现进行子类化非常好,因此它可以像这样在任何地方使用:

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

And at any part of your code you can use it as:

在代码的任何部分,您都可以将其用作:

[myNSDate isBetweenDate:thisNSDate andDate:thatNSDate];

(myNSDate, thisNSDate and thatNSDate are of course NSDates :)

(myNSDate, thisNSDate 和 thatNSDate 当然是 N​​SDates :)

回答by Imanou Petit

With Swift 5, you can use one of the two solutions below in order to check if a date occurs between two other dates.

使用 Swift 5,您可以使用以下两种解决方案之一来检查某个日期是否出现在其他两个日期之间。



#1. Using DateInterval's contains(_:)method

#1. usingDateIntervalcontains(_:)方法

DateIntervalhas a method called contains(_:). contains(_:)has the following declaration:

DateInterval有一个方法叫做contains(_:). contains(_:)有以下声明:

func contains(_ date: Date) -> Bool

Indicates whether this interval contains the given date.

指示此间隔是否包含给定日期。

The following Playground code shows how to use contains(_:)in order to check if a date occurs between two other dates:

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


#2. Using ClosedRange's contains(_:)method

#2. usingClosedRangecontains(_:)方法

ClosedRangehas a method called contains(_:). contains(_:)has the following declaration:

ClosedRange有一个方法叫做contains(_:). contains(_:)有以下声明:

func contains(_ element: Bound) -> Bool

Returns a Boolean value indicating whether the given element is contained within the range.

返回一个布尔值,指示给定元素是否包含在范围内。

The following Playground code shows how to use contains(_:)in order to check if a date occurs between two other dates:

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

回答by TheCodingArt

A better version in Swift:

一个更好的 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
    }
}