Вопрос по cocoa, objective-c – Как проверить, возникает ли NSDate между двумя другими NSDate

88

Я пытаюсь выяснить, попадает ли текущая дата в диапазон дат, используя NSDate.

Например, вы можете получить текущую дату / время, используя NSDate:

NSDate rightNow = [NSDate date];

Затем я хотел бы использовать эту дату, чтобы проверить, находится ли она в диапазоне9AM - 5PM.

Вы можете взглянуть на ответы наэтот вопро для получения дополнительной информации о том, как создавать объекты NSDate для определенного периода времени, например, с 17:00 до 21:0 Marc Charbonneau

Ваш Ответ

10   ответов
160

не стесняйтесь оставить его, и я отмечу его как правильное.

+ (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;
}
Код гольф! Компилятор должен замкнуть сравнение, сделав эффективность примерно равной вашей: return (([date Compare: beginDate]! = NSOrderedDescending) && ([Date Compare: endDate]! = NSOrderedAscending)); Tim
Это выглядит хорошо, но вы можете переименовать его примерно так: + (BOOL) date: (NSDate *) date isBetweenDate: (NSDate *) beginDate andDate: (NSDate *) endDate, чтобы избежать путаницы. Jeff Kelley
Еще лучше, я бы сделал это методом экземпляра (дополнение к NSDate), а не методом класса. Я бы пошел с этим: -isBetweenDate: andDate: Dave Batton
Превосходно! Я сделал категорию из этого:- (BOOL)isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate; Matteo Alessani
хорошее решение, вы даже можете сделать его менее подробным из-за короткого замыкания (и базовое приложение Де Моргана.return !([date compare:startDate] == NSOrderedAscending || [date compare:endDate] == NSOrderedDescending); Gabriele Petronella
14

@ kperryua для создания объектов NSDate, с которыми вы хотите сравнить. Из твоего ответа на свой вопрос, похоже, ты понял это.

Для сравнения дат я полностью согласен с@Ти комментарий к вашему ответу. Это более кратко, но на самом деле точно соответствует вашему коду, и я объясню почему.

+ (BOOL) date:(NSDate*)date isBetweenDate:(NSDate*)beginDate andDate:(NSDate*)endDate {
    return (([date compare:beginDate] != NSOrderedAscending) && ([date compare:endDate] != NSOrderedDescending));
}

Хотя может показаться, что оператор return должен оценивать оба операнда оператора &&, на самом деле это не так. Ключ " оценка короткого замыкания ", который реализован в самых разных языках программирования и, конечно, в C. В основном, операторы& а также&& "короткое замыкание", если первый аргумент равен 0 (или НЕТ, ноль и т. д.), а| а также|| сделать то же самое, если первый аргументн 0. Еслиdate предшествуетbeginDate, тест возвращаетсяNO даже не нужно сравнивать сendDate. По сути, он делает то же самое, что и ваш код, но одним оператором в одной строке, а не 5 (или 7, с пробелами).

Это задумано как конструктивный ввод, поскольку, когда программисты понимают, как их конкретный язык программирования оценивает логические выражения, они могут конструировать их более эффективно, не обращая особого внимания на эффективность. Однако есть похожие тесты, которыебыло б быть менее эффективным, так как не все операторы замкнуты. (Действительно, большинствоне могу короткое замыкание, такое как операторы числового сравнения.) В случае сомнений всегда можно быть явным при разделении логики, но код может быть намного более читабельным, если вы разрешите языку / компилятору обрабатывать мелочи для вас.

Understandable. Я понятия не имел, что Objective-C будет закорачивать оценки. Я верю твоему слову, что это так. Спасибо за разъяснение этого для меня. Полагаю, я отмечу вас как правильную, поскольку ваш ответ более лаконичен, чем мой ... и я кое-что узнал Brock Woolf
Не нужно верить мне на слово - я отстаиваю принцип «доверяй, но проверяй» (спасибо, Рональд Рейган!) Только для того, чтобы удовлетворить мое любопытство и узнать границы того, когда что-то работает, а что нет. Вы можете проверить это, выполнив && двух методов, которые регистрируют то, что они возвращают при вызове; вы заметите, что если первый вернет 0, второй никогда не будет вызван. Quinn Taylor
Конечно, я напишу что-нибудь для проверки. Brock Woolf
8

Версия Брука Вульфа в 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
    }
}
5

попадает ли текущая дата между двумя указанными точками времени (с 9:00 до 17:00 01.07.09), используйте NSCalendar и NSDateComponents, чтобы создать экземпляры NSDate для желаемого времени и сравнить их с текущей датой.

Если вы хотите знать, попадает ли текущая дата между этими двумя часами Каждый день, тогда ты мог бы пойти другим путем. Создайте объект NSDateComponents с помощью и NSCalendar и NSDate и сравните часовые компоненты.

2

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
0

Лучшая версия в 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
    }
}
3

очень приятно создавать подклассы реализации 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:)

Это здорово, спасибо! Supertecnoboff
4

const NSTimeInterval i = [date timeIntervalSinceReferenceDate];
return ([startDate timeIntervalSinceReferenceDate] <= i &&
        [endDate timeIntervalSinceReferenceDate] >= i);
2

Есть лучшее и более быстрое решение этой проблемы.

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 и выше.

0

чтобы проверить, встречается ли дата между двумя другими датами.

# 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

Похожие вопросы