What is the best way to know if a date is in the same week (or year or month) as another, preferably with an extension, and solely using Swift?
As a
You can use this extension that is based on the Objective-C code you've provided:
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
}
}
The default calendar here is the autoupdatingCurrent
so if user changes the calendar it will update accordingly. Also it uses variadic parameter components that allows you to specify any number of components without wrapping them into an array.
Example of usage:
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
EDIT
As @Leo Dabus pointed out we may use set here instead of array/variadic parameters - that way we'll avoid comparing the same components many times if user passes some duplicates to the method:
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
}
}
You can use calendar method isDate(equalTo:granularity:)
to check it as follow:
Xcode 11 • Swift 5.1
extension Date {
func isEqual(to date: Date, toGranularity component: Calendar.Component, in calendar: Calendar = .current) -> Bool {
calendar.isDate(self, equalTo: date, toGranularity: component)
}
func isInSameYear(as date: Date) -> Bool { isEqual(to: date, toGranularity: .year) }
func isInSameMonth(as date: Date) -> Bool { isEqual(to: date, toGranularity: .month) }
func isInSameWeek(as date: Date) -> Bool { isEqual(to: date, toGranularity: .weekOfYear) }
func isInSameDay(as date: Date) -> Bool { Calendar.current.isDate(self, inSameDayAs: date) }
var isInThisYear: Bool { isInSameYear(as: Date()) }
var isInThisMonth: Bool { isInSameMonth(as: Date()) }
var isInThisWeek: Bool { isInSameWeek(as: Date()) }
var isInYesterday: Bool { Calendar.current.isDateInYesterday(self) }
var isInToday: Bool { Calendar.current.isDateInToday(self) }
var isInTomorrow: Bool { Calendar.current.isDateInTomorrow(self) }
var isInTheFuture: Bool { self > Date() }
var isInThePast: Bool { self < Date() }
}