web-dev-qa-db-ja.com

NSDateが他の2つのNSDateの間で発生するかどうかを確認する方法

NSDateを使用して、現在の日付が日付範囲内にあるかどうかを把握しようとしています。

たとえば、NSDateを使用して現在の日付/時刻を取得できます。

NSDate rightNow = [NSDate date];

その日付を使用して、9AM-5PMの範囲内にあるかどうかを確認します。

90
Brock Woolf

私は解決策を思いつきました。より良い解決策がある場合は、お気軽にお任せください。正しいものとしてマークします。

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

最初の部分では、@ 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|および||最初の引数がnot0の場合、同じことを行います。datebeginDate、テストはNOと比較する必要なしにendDateを返します。基本的に、コードと同じことを行いますが、5行(または空白を含む7行)ではなく、1行で1つのステートメントを実行します。

これは、プログラマーが特定のプログラミング言語が論理式を評価する方法を理解するとき、効率をあまり考慮せずにより効果的に構築できるため、建設的な入力として意図されています。ただし、wouldは、すべての演算子が短絡するわけではないため、効率が低下する同様のテストがあります。 (実際、数値比較演算子など、ほとんどのcannotショートサーキット。)疑わしい場合は、ロジックを分解することを明示的に指定することは常に安全ですが、コードはさらに大きくなる可能性があります言語/コンパイラにささいなことを処理させると読みやすくなります。

13
Quinn Taylor

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

現在の日付が特定の2つの時点(2009年7月1日の午前9時から午後5時)の間にあるかどうかを知りたい場合は、NSCalendarおよびNSDateComponentsを使用して、目的の時間のNSDateインスタンスを構築し、現在の日付と比較します。

現在の日付がこれらの2時間の間にあるかどうかを知りたい場合は、every dayの場合、おそらく他の方法を選択できます。 NSCalendarとNSDateを使用してNSDateComponentsオブジェクトを作成し、時間コンポーネントを比較します。

4
kperryua

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です:)

3
MiQUEL

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)

次に、containsDateIntervalメソッドを使用して、日付が間隔内にあるかどうかを確認します。

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

この問題に対するより良い、より迅速な解決策があります。

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以上で使用できます。

3
Rehan Ali

これは、次のように日付の時間間隔を使用して簡単に実現できます。

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

Swift 5を使用すると、以下の2つのソリューションのいずれかを使用して、日付が他の2つの日付の間に発生するかどうかを確認できます。


#1。 DateIntervalcontains(_:)メソッドを使用する

DateIntervalには contains(_:) というメソッドがあります。 contains(_:)には次の宣言があります。

_func contains(_ date: Date) -> Bool
_

この間隔に指定の日付が含まれるかどうかを示します。

次のPlaygroundコードは、contains(_:)を使用して、日付が他の2つの日付の間に発生するかどうかを確認する方法を示しています。

_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。 ClosedRangecontains(_:)メソッドを使用する

ClosedRangeには contains(_:) というメソッドがあります。 contains(_:)には次の宣言があります。

_func contains(_ element: Bound) -> Bool
_

指定された要素が範囲内に含まれているかどうかを示すブール値を返します。

次のPlaygroundコードは、contains(_:)を使用して、日付が他の2つの日付の間に発生するかどうかを確認する方法を示しています。

_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
_
1
Imanou Petit

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