For iOS 13 or later you can use RelativeDateTimeFormatter
let relativeDateTimeFormatter = RelativeDateTimeFormatter()
relativeDateTimeFormatter.dateTimeStyle = .named
relativeDateTimeFormatter.unitsStyle = .full
let date = Date.init(timeIntervalSinceNow: -60*60*24)
relativeDateTimeFormatter.string(for: date) // "yesterday"
edit/update:
If you would like to support iOS 11 you would need to implement your own relative date formatter. You can use Calendar method isDateInToday and isDateInYesterday to combine a relative date formatter with date components formatter. Note that there is no need to check the time interval for setting a single unit in your date components formatter you can set the allowed units of your date components formatter, just make sure you set them respecting the desired priority to be displayed:
// This will avoid creating a formatter every time you call relativeDateFormatted property
extension Formatter {
static let dateComponents: DateComponentsFormatter = {
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [.day, .month, .year] // check the order of the units it does matter when allowing only 1 unit to be displayed
dateComponentsFormatter.maximumUnitCount = 1
dateComponentsFormatter.unitsStyle = .full
return dateComponentsFormatter
}()
static let relativeDate: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.doesRelativeDateFormatting = true
dateFormatter.timeStyle = .none
dateFormatter.dateStyle = .medium
return dateFormatter
}()
}
extension Date {
var relativeDateFormatted: String {
Calendar.current.isDateInToday(self) || Calendar.current.isDateInYesterday(self) ?
Formatter.relativeDate.string(from: self) :
Formatter.dateComponents.string(from: self, to: Date()) ?? ""
}
}
Playground testing:
let date1 = DateComponents(calendar: .current, year: 2020, month: 9, day: 4, hour: 5).date!
let date2 = DateComponents(calendar: .current, year: 2020, month: 9, day: 3, hour: 23, minute: 50).date!
let date3 = DateComponents(calendar: .current, year: 2020, month: 8, day: 25, hour: 10).date!
let date4 = DateComponents(calendar: .current, year: 2020, month: 8, day: 3).date!
let date5 = DateComponents(calendar: .current, year: 2019, month: 8, day: 27).date!
date1.relativeDateFormatted // "Today"
date2.relativeDateFormatted // "Yesterday"
date3.relativeDateFormatted // "10 days"
date4.relativeDateFormatted // "1 month"
date5.relativeDateFormatted // "1 year"