Próbuję dowiedzieć się, czy aktualna data mieści się w zakresie dat za pomocą NSDate.
Na przykład możesz pobrać aktualną datę / godzinę za pomocą NSDate:
NSDate rightNow = [NSDate date];
Chciałbym wtedy wykorzystać tę datę, aby sprawdzić, czy mieści się w przedziale 9-17 .
objective-c
cocoa
cocoa-touch
datetime
nsdate
Brock Woolf
źródło
źródło
Odpowiedzi:
Wymyśliłem rozwiązanie. Jeśli masz lepsze rozwiązanie, możesz je zostawić, a zaznaczę je jako poprawne.
+ (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; }
źródło
- (BOOL)isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate;
return !([date compare:startDate] == NSOrderedAscending || [date compare:endDate] == NSOrderedDescending);
W pierwszej części użyj odpowiedzi z @kperryua, aby skonstruować obiekty NSDate, z którymi chcesz porównać. Z Twojej odpowiedzi na własne pytanie wynika, że już to rozgryzłeś.
Jeśli chodzi o porównanie dat, całkowicie zgadzam się z komentarzem @Tim dotyczącym Twojej odpowiedzi. Jest bardziej zwięzły, ale w rzeczywistości dokładnie odpowiada Twojemu kodowi i wyjaśnię dlaczego.
+ (BOOL) date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate { return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending)); }
Chociaż może się wydawać, że instrukcja return musi oceniać oba operandy operatora &&, w rzeczywistości tak nie jest. Kluczem jest „ ocena zwarcia ”, która jest zaimplementowana w wielu różnych językach programowania, a na pewno w C. Zasadniczo operatory
&
i&&
„zwarcie”, jeśli pierwszym argumentem jest 0 (lub NIE, zero, itp.) , while|
i||
zrób to samo, jeśli pierwszy argument nie jest równy 0. Jeśli wystąpidate
wcześniejbeginDate
, test zwracaNO
bez konieczności porównywania zendDate
. Zasadniczo robi to samo, co twój kod, ale w pojedynczej instrukcji w jednym wierszu, a nie w 5 (lub 7, z białymi znakami).Ma to być konstruktywne dane wejściowe, ponieważ gdy programiści rozumieją sposób, w jaki ich język programowania ocenia wyrażenia logiczne, mogą je konstruować bardziej efektywnie bez zbytniej wydajności. Istnieją jednak podobne testy, które byłyby mniej wydajne, ponieważ nie wszyscy operatorzy powodują zwarcie. (Rzeczywiście, większość nie może powodować zwarć, takich jak numeryczne operatory porównania.) W razie wątpliwości zawsze bezpiecznie jest rozbić logikę, ale kod może być znacznie bardziej czytelny, gdy pozwolisz językowi / kompilatorowi zająć się drobiazgami dla Was.
źródło
Wersja Brock Woolf w 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 } }
źródło
Jeśli chcesz wiedzieć, czy bieżąca data przypada między dwoma podanymi punktami w czasie (9:00 - 17:00 dnia 7/1/09), użyj NSCalendar i NSDateComponents, aby zbudować instancje NSDate dla żądanych godzin i porównać je z bieżącą datą.
Jeśli chcesz wiedzieć, czy aktualna data przypada między tymi dwiema godzinami każdego dnia, prawdopodobnie możesz pójść w drugą stronę. Utwórz obiekt NSDateComponents z NSCalendar i NSDate i porównaj składniki godzinowe.
źródło
Jeśli możesz kierować reklamy na system iOS 10.0 + / macOS 10.12+, użyj
DateInterval
klasy.Najpierw utwórz przedział dat z datą początkową i końcową:
let start: Date = Date() let middle: Date = Date() let end: Date = Date() let dateInterval: DateInterval = DateInterval(start: start, end: end)
Następnie sprawdź, czy data znajduje się w przedziale przy użyciu
contains
metodyDateInterval
:let dateIsInInterval: Bool = dateInterval.contains(middle) // true
źródło
Można to łatwo osiągnąć, korzystając z przedziałów czasowych dat, na przykład:
const NSTimeInterval i = [date timeIntervalSinceReferenceDate]; return ([startDate timeIntervalSinceReferenceDate] <= i && [endDate timeIntervalSinceReferenceDate] >= i);
źródło
Kontynuując pracę z rozwiązaniami Quinna i Brocka, bardzo dobrze jest podklasować implementację NSDate, więc może być używana wszędzie w następujący sposób:
-(BOOL) isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate { return (([self compare:beginDate] != NSOrderedAscending) && ([self compare:endDate] != NSOrderedDescending)); }
W dowolnej części kodu możesz go użyć jako:
[myNSDate isBetweenDate:thisNSDate andDate:thatNSDate];
(myNSDate, thisNSDate i thatNSDate to oczywiście NSDates :)
źródło
Istnieje lepsze i szybsze rozwiązanie tego problemu.
extention Date { func isBetween(from startDate: Date,to endDate: Date) -> Bool { let result = (min(startDate, endDate) ... max(startDate, endDate)).contains(self) return result } }
Wtedy możesz to tak nazwać.
todayDate.isBetween(from: startDate, to: endDate)
Nawet ty możesz przekazać datę losowo, ponieważ to rozszerzenie sprawdza, który z nich jest minimalny, a który nie.
możesz go używać w wersji Swift 3 i nowszych.
źródło
Dzięki Swift 5 możesz użyć jednego z dwóch poniższych rozwiązań, aby sprawdzić, czy data przypada między dwiema innymi datami.
# 1. Korzystanie
DateInterval
zcontains(_:)
metodyDateInterval
ma metodę o nazwiecontains(_:)
.contains(_:)
posiada następującą deklarację:func contains(_ date: Date) -> Bool
Poniższy kod Playground pokazuje, jak używać
contains(_:)
, aby sprawdzić, czy data występuje między dwiema innymi datami: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. Korzystanie
ClosedRange
zcontains(_:)
metodyClosedRange
ma metodę o nazwiecontains(_:)
.contains(_:)
posiada następującą deklarację:func contains(_ element: Bound) -> Bool
Poniższy kod Playground pokazuje, jak używać
contains(_:)
, aby sprawdzić, czy data występuje między dwiema innymi datami: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
źródło
Lepsza wersja w 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 } }
źródło