Является ли дата в одну и ту же неделю, месяц, год другой даты в быстрой

Каков наилучший способ узнать, является ли дата на той же неделе (или году или месяце) другой, желательно с расширением и исключительно с использованием Swift?

Например, в Objective-C у меня есть

- (BOOL)isSameWeekAs:(NSDate *)date {
    NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self];
    NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
    return ([today weekOfYear]   == [otherDay weekOfYear] &&
            [today year]         == [otherDay year] &&
            [today era]          == [otherDay era]);
}

Пожалуйста, не предлагайте решения, связывающие Date с NSDate

Ответ 1

Вы можете использовать метод календаря isDate(equalTo:granularity:) чтобы проверить его следующим образом:

extension Date {
    func isInSameWeek(date: Date) -> Bool {
        return Calendar.current.isDate(self, equalTo: date, toGranularity: .weekOfYear)
    }
    func isInSameMonth(date: Date) -> Bool {
        return Calendar.current.isDate(self, equalTo: date, toGranularity: .month)
    }
    func isInSameYear(date: Date) -> Bool {
        return Calendar.current.isDate(self, equalTo: date, toGranularity: .year)
    }
    func isInSameDay(date: Date) -> Bool {
        return Calendar.current.isDate(self, equalTo: date, toGranularity: .day)
    }
    var isInThisWeek: Bool {
        return isInSameWeek(date: Date())
    }
    var isInYesterday: Bool {
        return Calendar.current.isDateInYesterday(self)
    }
    var isInToday: Bool {
        return Calendar.current.isDateInToday(self)
    }
    var isInTomorrow: Bool {
        return Calendar.current.isDateInTomorrow(self)
    }
    var isInTheFuture: Bool {
        return Date() < self
    }
    var isInThePast: Bool {
        return self < Date()
    }
}

Ответ 2

Вы можете использовать это расширение, основанное на коде Objective-C, который вы указали:

extension Date {
    func hasSame(_ components: Calendar.Component..., as date: Date, using calendar: Calendar = .autoupdatingCurrent) -> Bool {
             return components.filter { calendar.component($0, from: date) != calendar.component($0, from: self) }.isEmpty
    }
}

Календарь по умолчанию - это autoupdatingCurrent поэтому, если пользователь изменяет календарь, он будет соответствующим образом обновляться. Также он использует переменные компоненты параметров, которые позволяют вам указать любое количество компонентов, не упаковывая их в массив.

Пример использования:

let date1 = Date()
let date2 = Date()
let date3 = Date(timeIntervalSince1970: 30.0)

print(date1.hasSame(.weekOfYear, .day, .hour, as: date2)) // true
print(date1.hasSame(.weekOfYear, as: date3)) // false

РЕДАКТИРОВАТЬ

Как отметил @Leo Dabus, мы можем использовать здесь set вместо параметров array/variadic - таким образом мы не будем многократно сравнивать одни и те же компоненты, если пользователь передает некоторые дубликаты методу:

extension Date {
    func hasSame(_ components: Set<Calendar.Component>, as date: Date, using calendar: Calendar = .autoupdatingCurrent) -> Bool {
             return components.filter { calendar.component($0, from: date) != calendar.component($0, from: self) }.isEmpty
    }
}