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


90

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

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

NSDate rightNow = [NSDate date];

次に、その日付を使用して、午前9時から午後5時の範囲にあるかどうかを確認します。


1
あなたはへの回答を見てとることができ、この質問を NSDateは、5 pm-9pmとして、特定の期間のためのオブジェクトを作成する方法の詳細については。
マークシャルボノー、

回答:


167

私は解決策を思いついた。より良い解決策があれば、遠慮なくそれを残してください。私はそれを正しいものとしてマークします。

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

3
見栄えは良いですが、次のように名前を変更することをお勧めします。+(BOOL)date:(NSDate *)date isBetweenDate:(NSDate *)beginDate andDate:(NSDate *)endDate混乱を避けるため
ジェフケリー

3
コードゴルフ!コンパイラーは比較を短絡し、効率をおおよその値に等しくする必要があります。return(([date compare:beginDate]!= NSOrderedDescending)&&([date compare:endDate]!= NSOrderedAscending));
ティム

1
さらに良いことに、これをクラスメソッドではなく、インスタンスメソッド(NSDateへの追加)にします。私はこれで行きます:-isBetweenDate:andDate:
Dave

4
優れた!私はこれからカテゴリを作成しました:- (BOOL)isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate;
Matteo Alessani

2
素敵なソリューション、あなたも短絡(および基本的なド・モルガンのアプリケーションによって、それはそれほど冗長にすることができます。return !([date compare:startDate] == NSOrderedAscending || [date compare:endDate] == NSOrderedDescending);
ガブリエレPetronella

13

最初の部分では、@ 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 でない場合も同じことを|行い||ます。前に来る場合、テストはと比較する必要さえなく戻ります。基本的には、コードと同じことを行いますが、5(または7、空白あり)ではなく、1行で1つのステートメントを実行します。datebeginDateNOendDate

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


1
分かります。Objective-Cが評価を短絡させるとは思いもしませんでした。私はそれについてあなたの言葉を引き受けます。整理してくれてありがとう。私はあなたの答えが私のものよりも簡潔なので、私はあなたを正しいとマークします...そして私は何かを学びました:)
Brock Woolf

私の好奇心を満たし、何かが機能する場合と機能しない場合の境界を知るためにのみ、私は「信頼するが、検証する」という原則を支持します(ありがとう、ロナルドレーガン!)。呼び出されたときに何が返されるかをログに記録する2つのメソッドの&&を実行することで、それを確認できます。最初のコードが0を返す場合、2番目のコードが呼び出されることはありません。
クインテイラー

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

4

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

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


4

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

3

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

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

3

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

この問題には、より適切で迅速な解決策があります。

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


2

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

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
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.