I want to use doesRelativeDateFormatting
with Swift in order to get more human-readable dates, such as "today", or "tomorrow" when displaying dates on my app. However, when displaying non-relative dates, I would like to show a custom style, such as "Wed, Feb 10 '18".
So far, I could use one of the predefined dateStyle
with my DateFormatter object, such as .short
or .medium
, but none of those display an abbreviation of both the weekday and of the month. And when using a custom format from a string, such as "EEE, MMM d yy", I lose the relative dates.
Is that a way to use both and display relative dates when they exist, and custom date for all the other dates?
There's no direct way to get relative formatting and a custom format when the not using a relative format. At best you can specify the style but not the format.
One solution is to use a helper method that uses three date formatters. One that uses relative formatting with a desired style, one that isn't relative but uses the same style, and one that uses your custom format for non-relative dates.
func formatDate(_ date: Date) -> String {
// Setup the relative formatter
let relDF = DateFormatter()
relDF.doesRelativeDateFormatting = true
relDF.dateStyle = .long
relDF.timeStyle = .medium
// Setup the non-relative formatter
let absDF = DateFormatter()
absDF.dateStyle = .long
absDF.timeStyle = .medium
// Get the result of both formatters
let rel = relDF.string(from: date)
let abs = absDF.string(from: date)
// If the results are the same then it isn't a relative date.
// Use your custom formatter. If different, return the relative result.
if (rel == abs) {
let fullDF = DateFormatter()
fullDF.setLocalizedDateFormatFromTemplate("EEE, MMM d yy")
return fullDF.string(from: date)
} else {
return rel
}
}
print(formatDate(Date()))
print(formatDate(Calendar.current.date(byAdding: .day, value: 1, to: Date())!))
print(formatDate(Calendar.current.date(byAdding: .day, value: 7, to: Date())!))
Output:
Today at 11:01:16 AM
Tomorrow at 11:01:16 AM
Tue, Feb 20, 18
If you need to format lots of dates you will want to modify this code so it creates all of the formatters once and then reuses them in this method.