J'essaie de déterminer si la date actuelle est comprise dans une plage de dates à l'aide de NSDate.
Par exemple, vous pouvez obtenir la date et l'heure actuelles à l'aide de NSDate:
NSDate rightNow = [NSDate date];
Je voudrais ensuite utiliser cette date pour vérifier si elle est dans la plage de 9 heures-17 heures.
Je suis venu avec une solution. Si vous avez une meilleure solution, n'hésitez pas à la laisser et je la marquerai comme correcte.
+ (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;
}
Pour la première partie, utilisez la réponse de @kperryua pour construire les objets NSDate avec lesquels vous souhaitez comparer. De votre réponse à votre propre question, il semble que vous ayez compris cela.
Pour comparer réellement les dates, je suis tout à fait d’accord avec le commentaire de @Tim sur votre réponse. C'est plus concis mais en réalité exactement équivalent à votre code, et je vais vous expliquer pourquoi.
+ (BOOL) date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending));
}
Bien qu'il puisse sembler que l'instruction return doit évaluer les deux opérandes de l'opérateur &&, ce n'est en réalité pas le cas. La clé est " court-circuit evaluation ", qui est implémentée dans une grande variété de langages de programmation, et certainement en C. En gros, les opérateurs &
et &&
"court-circuit" si le premier argument est 0 (ou NO, nil, etc.), tandis que |
et ||
font la même chose si le premier argument est not 0. Si date
vient avant beginDate
, le test renvoie NO
sans même avoir besoin de comparer avec endDate
. En gros, il fait la même chose que votre code, mais dans une seule déclaration sur une ligne, pas 5 (ou 7, avec des espaces).
Ceci est conçu comme une contribution constructive, car lorsque les programmeurs comprennent la manière dont leur langage de programmation évalue les expressions logiques, ils peuvent les construire plus efficacement sans trop d’efficacité. Cependant, il existe des tests similaires qui seraient moins efficaces, étant donné que tous les opérateurs ne font pas de court-circuit. (En effet, la plupart des ne peuvent pas court-circuits, tels que les opérateurs de comparaison numériques.) En cas de doute, il est toujours prudent de clarifier la logique, mais le code peut être beaucoup plus lisible lorsque/compilateur gère les petites choses pour vous.
Version de Brock Woolf dans 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
}
}
Si vous voulez savoir si la date actuelle se situe entre deux moments donnés (9h - 17h le 7/1/09), utilisez NSCalendar et NSDateComponents pour créer des instances NSDate aux heures souhaitées et comparez-les à la date du jour.
Si vous voulez savoir si la date actuelle se situe entre ces deux heures toutes jours, vous pouvez probablement procéder dans l'autre sens. Créez un objet NSDateComponents avec et NSCalendar et votre NSDate et comparez les composants horaires.
Ceci peut être accompli facilement en utilisant les intervalles de temps des dates, comme ceci:
const NSTimeInterval i = [date timeIntervalSinceReferenceDate];
return ([startDate timeIntervalSinceReferenceDate] <= i &&
[endDate timeIntervalSinceReferenceDate] >= i);
Poursuivre avec les solutions de Quinn et de Brock est très agréable de mettre en œuvre l’implémentation de NSDate afin qu’il puisse être utilisé partout comme ceci:
-(BOOL) isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
return (([self compare:beginDate] != NSOrderedAscending) && ([self compare:endDate] != NSOrderedDescending));
}
Et à n'importe quelle partie de votre code, vous pouvez l'utiliser comme:
[myNSDate isBetweenDate:thisNSDate andDate:thatNSDate];
(myNSDate, thisNSDate et thatNSDate sont bien sûr des NSDates :)
Si vous pouvez cibler iOS 10.0 +/macOS 10.12+, utilisez la classe DateInterval
.
Tout d’abord, créez un intervalle de dates avec une date de début et de fin:
let start: Date = Date()
let middle: Date = Date()
let end: Date = Date()
let dateInterval: DateInterval = DateInterval(start: start, end: end)
Ensuite, vérifiez si la date est dans l'intervalle en utilisant la méthode contains
de DateInterval
:
let dateIsInInterval: Bool = dateInterval.contains(middle) // true
Il existe une solution meilleure et plus rapide à ce problème.
extention Date {
func isBetween(from startDate: Date,to endDate: Date) -> Bool {
let result = (min(startDate, endDate) ... max(startDate, endDate)).contains(self)
return result
}
}
Ensuite, vous pouvez l'appeler comme ça.
todayDate.isBetween(from: startDate, to: endDate)
Même vous pouvez passer la date au hasard car cette extension vérifie lequel est minimum et lequel n’est pas.
vous pouvez l'utiliser dans Swift 3 et au-dessus.
Avec Swift 4.2 et iOS 12, vous pouvez utiliser l'une des deux solutions ci-dessous afin de vérifier si une date se situe entre deux autres dates.
DateInterval
's contains(_:)
DateInterval
a une méthode appelée contains(_:)
. contains(_:)
a la déclaration suivante:
func contains(_ date: Date) -> Bool
Indique si cet intervalle contient la date donnée.
Le code de terrain de jeu suivant montre comment utiliser contains(_:)
afin de vérifier si une date se produit entre deux autres dates:
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
's contains(_:)
ClosedRange
a une méthode appelée contains(_:)
. contains(_:)
a la déclaration suivante:
func contains(_ element: Bound) -> Bool
Retourne une valeur booléenne indiquant si l'élément donné est contenu dans la plage.
Le code de terrain de jeu suivant montre comment utiliser contains(_:)
afin de vérifier si une date se produit entre deux autres dates:
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
Une meilleure version dans 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
}
}