In reference to this old question
I am not sure why I have a remainder of one hour, when subtracting weeks and days from today's date.
dump(Date().xWeeks(-13).xDays(-2).elapsedDescription)
extension Date {
/// Returns a new date that is 'x' number of days hence the recevier.
public func xDays(_ x:Int) -> Date {
return Calendar.current.date(byAdding: .day, value: x, to: self)!
}
/// Returns a new date that is 'x' number of weeks (of year) hence the recevier.
public func xWeeks(_ x:Int) -> Date {
return Calendar.current.date(byAdding: .weekOfYear, value: x, to: self)!
}
/// The count of hours hence the receiver. Today's date is established using the device clock.
public func elapsedHours(toDate: Date) -> Int{
return Calendar.current.dateComponents([.hour], from: self, to: toDate).hour!
}
/// The count of days hence the receiver. Today's date is established using the device clock.
public func elapsedDays(toDate: Date) -> Int{
return Calendar.current.dateComponents([.day], from: self, to: toDate).day!
}
/// The count of weeks hence the receiver. Today's date is established using the device clock.
public func elapsedWeeks(toDate: Date) -> Int{
return Calendar.current.dateComponents([.weekOfYear], from: self, to: toDate).weekOfYear!
}
public var elapsedDescription: String {
let toDate = Date()
let weekValue = elapsedWeeks(toDate: toDate) == 1 ? "week" : "weeks"
if elapsedWeeks(toDate: toDate) > 0 {
let dayRemainder = elapsedDays(toDate: toDate)-elapsedWeeks(toDate: toDate)*7
if dayRemainder > 0 {
let dayValue = dayRemainder == 1 ? "day" : "days"
let remainingHours = elapsedHours(toDate: toDate)-elapsedWeeks(toDate: toDate)*7*24 - (dayRemainder*24)
if remainingHours > 0 {
let hourValue = remainingHours == 1 ? "hour" : "hours"
return "\(elapsedWeeks(toDate: toDate)) \(weekValue), \(dayRemainder) \(dayValue) and \(remainingHours) \(hourValue)"
} else {
return "\(elapsedWeeks(toDate: toDate)) \(weekValue) and \(dayRemainder) \(dayValue)"
}
} else {
return "\(elapsedWeeks(toDate: toDate)) \(weekValue)"
}
} else if elapsedHours(toDate: toDate) > 0 {
let hourValue = elapsedHours(toDate: toDate) == 1 ? "hour" : "hours"
return "\(elapsedHours(toDate: toDate)) \(hourValue)"
} else {
return ""
}
}
}