Como verificar se um NSDate ocorre entre dois outros NSDates
-
21-08-2019 - |
Pergunta
Eu estou tentando descobrir se ou não a data atual cai dentro de um intervalo de datas usando NSDate.
Por exemplo, você pode obter a data / hora atual usando NSDate:
NSDate rightNow = [NSDate date];
Em seguida, gostaria de usar essa data para verificar se ele está na faixa de 9:00 -. 05:00
Solução
Eu vim com uma solução. Se você tiver uma solução melhor, fique à vontade para deixá-lo e eu vou marcá-lo como correto.
+ (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;
}
Outras dicas
Para a primeira parte, use a resposta de @kperryua para construir o NSDate objetos que você deseja comparar com. Da sua resposta à sua própria pergunta, parece que você tem que descobri.
Para realmente comparar as datas, eu concordo totalmente com @ Tim comentário que está em sua resposta. É mais concisa mas, na verdade exatamente equivalente ao seu código, e vou explicar porquê.
+ (BOOL) date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending));
}
Embora possa parecer que a instrução de retorno deve avaliar ambos os operandos do operador &&, isso não é realmente o caso. A chave é " curto-circuito avaliação", que é implementado em uma ampla variedade de programação línguas, e certamente em C. Basicamente, os operadores &
e &&
"curto-circuito" se o primeiro argumento é 0 (ou NÃO, nil, etc.), enquanto < strong> |
e ||
fazer o mesmo se o primeiro argumento é não 0. Se date
vem antes beginDate
, o teste retorna NO
, mesmo sem a necessidade de comparar com endDate
. Basicamente, ele faz a mesma coisa que o seu código, mas em uma única instrução em uma linha, não 5 (ou 7, com espaços em branco).
Este é concebido como contribuição construtiva, desde quando programadores compreender a forma como a sua linguagem de programação específica avalia expressões lógicas, eles podem construí-los de forma mais eficaz, sem tanto sobre a eficiência. No entanto, existem testes semelhantes que seria ser menos eficiente, uma vez que nem todos os operadores de curto-circuito. (Na verdade, a maioria não pode de curto-circuito, tais como operadores de comparação numérica.) Em caso de dúvida, é sempre mais seguro para ser explícito em quebrando sua lógica, mas o código pode ser muito mais legível quando você deixar o linguagem / compilador lidar com as pequenas coisas para você.
Versão Brock Woolf em 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
}
}
Se você quer saber se a data atual cai entre dois pontos dados no tempo (nove horas - cinco horas em 7/1/09), use NSCalendar e NSDateComponents para construir instâncias NSDate para os tempos desejados e compará-los com a data atual .
Se você quer saber se a data atual cai entre estas duas horas todas dia, então você provavelmente poderia ir por outro caminho. Criar um NSDateComponents objeto com e NSCalendar e seu NSDate e comparar os componentes hora.
Isso pode ser feito facilmente usando intervalos de tempo das datas, assim:
const NSTimeInterval i = [date timeIntervalSinceReferenceDate];
return ([startDate timeIntervalSinceReferenceDate] <= i &&
[endDate timeIntervalSinceReferenceDate] >= i);
Continuando com soluções Brock's Quinn e, é muito agradável para subclasse implementação NSDate, para que ele possa ser usado em todos os lugares como este:
-(BOOL) isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
return (([self compare:beginDate] != NSOrderedAscending) && ([self compare:endDate] != NSOrderedDescending));
}
E, em qualquer parte do seu código você pode usá-lo como:
[myNSDate isBetweenDate:thisNSDate andDate:thatNSDate];
(myNSDate, thisNSDate e thatNSDate são naturalmente NSDates :)
Se você pode direcionar iOS 10,0 + / MacOS 10.12+, em seguida, usar a classe DateInterval
.
Primeiro, crie um intervalo de datas com uma data de início e término:
let start: Date = Date()
let middle: Date = Date()
let end: Date = Date()
let dateInterval: DateInterval = DateInterval(start: start, end: end)
Em seguida, verifique se a data é no intervalo usando o método contains
de DateInterval
:
let dateIsInInterval: Bool = dateInterval.contains(middle) // true
Não é melhor e solução mais swifty para este problema.
extention Date {
func isBetween(from startDate: Date,to endDate: Date) -> Bool {
let result = (min(startDate, endDate) ... max(startDate, endDate)).contains(self)
return result
}
}
Depois, você pode chamá-lo assim.
todayDate.isBetween(from: startDate, to: endDate)
Mesmo que você pode passar data aleatória a essa extensão verifica qual é mínimo e que um em não.
Você pode usá-lo em Swift 3 e acima.
Com Swift 5, você pode usar uma das duas soluções a seguir, a fim de verificar se uma data ocorre entre duas outras datas.
# 1. Usando o método DateInterval
de contains(_:)
DateInterval
tem um método chamado contains(_:)
. contains(_:)
tem a seguinte declaração:
func contains(_ date: Date) -> Bool
Indica se este intervalo contém a data dada.
Os seguintes mostra o código Parque como usar contains(_:)
, a fim de verificar se uma data ocorre entre duas outras datas:
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. Usando o método ClosedRange
de contains(_:)
ClosedRange
tem um método chamado contains(_:)
. contains(_:)
tem a seguinte declaração:
func contains(_ element: Bound) -> Bool
Retorna um valor booleano que indica se o elemento de dado está contido dentro do intervalo.
Os seguintes mostra o código Parque como usar contains(_:)
, a fim de verificar se uma data ocorre entre duas outras datas:
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
Uma versão melhor em 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
}
}