Я пытаюсь выяснить, попадает ли текущая дата в диапазон дат, используя NSDate.
Например, вы можете получить текущую дату / время с помощью NSDate:
NSDate rightNow = [NSDate date];
Затем я хотел бы использовать эту дату, чтобы проверить, находится ли она в диапазоне с 9 утра до 5 вечера .
objective-c
cocoa
cocoa-touch
datetime
nsdate
Брок Вульф
источник
источник
Ответы:
Я придумал решение. Если у вас есть лучшее решение, не стесняйтесь оставлять его, и я отмечу его как правильное.
+ (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. Еслиdate
предшествуетbeginDate
, тест возвращаетсяNO
без необходимости даже сравнивать сendDate
. По сути, он делает то же самое, что и ваш код, но в одном операторе в одной строке, а не в 5 (или 7, с пробелами).Это задумано как конструктивный ввод, поскольку, когда программисты понимают, как их конкретный язык программирования оценивает логические выражения, они могут создавать их более эффективно, не особо заботясь об эффективности. Однако существуют аналогичные тесты, которые были бы менее эффективными, поскольку не все операторы замыкают накоротко. (В самом деле, большинство из них не может замыкать короткое замыкание, например, операторы числового сравнения.) В случае сомнений всегда безопасно явным образом разбивать логику на части, но код может быть намного более читабельным, если вы позволите языку / компилятору обрабатывать мелочи. для тебя.
источник
Версия Брока Вульфа в 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 } }
источник
Если вы хотите знать, попадает ли текущая дата между двумя заданными моментами времени (с 9 утра до 5 вечера 1 июля 2009 г.), используйте NSCalendar и NSDateComponents для создания экземпляров NSDate для желаемого времени и сравните их с текущей датой.
Если вы хотите знать, попадает ли текущая дата между этими двумя часами каждый день, вы, вероятно, можете пойти другим путем. Создайте объект NSDateComponents с NSCalendar и вашим NSDate и сравните компоненты часа.
источник
Если вы можете настроить таргетинг на 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
источник
Это легко сделать, используя временные интервалы дат, например:
const NSTimeInterval i = [date timeIntervalSinceReferenceDate]; return ([startDate timeIntervalSinceReferenceDate] <= i && [endDate timeIntervalSinceReferenceDate] >= i);
источник
Продолжая работу с решениями Куинна и Брока, очень приятно создать подкласс реализации 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 вы можете использовать одно из двух решений ниже, чтобы проверить, наступает ли дата между двумя другими датами.
№1. Использование
DateInterval
«Scontains(_:)
методDateInterval
имеет метод под названиемcontains(_:)
.contains(_:)
имеет следующее объявление:func contains(_ date: Date) -> Bool
Следующий код игровой площадки показывает, как использовать
contains(_:)
, чтобы проверить, происходит ли дата между двумя другими датами: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. Использование
ClosedRange
«Scontains(_:)
методClosedRange
имеет метод под названиемcontains(_:)
.contains(_:)
имеет следующее объявление:func contains(_ element: Bound) -> Bool
Следующий код игровой площадки показывает, как использовать
contains(_:)
, чтобы проверить, происходит ли дата между двумя другими датами: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 } }
источник