NSDateを使用して、現在の日付が日付範囲内にあるかどうかを確認しようとしています。
たとえば、NSDateを使用して現在の日付/時刻を取得できます。
NSDate rightNow = [NSDate date];
次に、その日付を使用して、午前9時から午後5時の範囲にあるかどうかを確認します。
回答:
私は解決策を思いついた。より良い解決策があれば、遠慮なくそれを残してください。私はそれを正しいものとしてマークします。
+ (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;
}
- (BOOL)isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate;
return !([date compare:startDate] == NSOrderedAscending || [date compare:endDate] == NSOrderedDescending);
最初の部分では、@ 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つのステートメントを実行します。date
beginDate
NO
endDate
これは、建設的な入力として意図されています。プログラマーが特定のプログラミング言語が論理式を評価する方法を理解すると、効率をあまり気にすることなく、より効率的にそれらを構築できるからです。ただし、すべての演算子が短絡するわけではないため、効率が低下する同様のテストがあります。(実際、ほとんどは数値比較演算子のように短絡することはできません。)疑わしい場合は、ロジックを分解する際に明示的にするのが常に安全ですが、言語/コンパイラーが小さなことを処理するようにすると、コードはずっと読みやすくなります。あなたのために。
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
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です:)
この問題には、より適切で迅速な解決策があります。
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では、以下の2つのソリューションのいずれかを使用して、日付が他の2つの日付の間にあるかどうかを確認できます。
DateInterval
のcontains(_:)
方法を使用する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
ClosedRange
のcontains(_:)
方法を使用する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
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
}
}