I’m trying to write code to simply describe how much time has elapsed since an event, but described in only one term, eg. years, months, days, hours, minutes…
It shouldn’t show the exact elapsed time, just a general sense of how long ago it was.
I’ve written this code but it feels like there should be a much cleaner and simpler way of doing this. Any suggestions?
func fuzzyDistanceToNow(includeJustNow blIncludeJustNow: Bool, appendString stAppendString: String) -> String {
let dDistance = abs(self.distance(to: Date())) //Distance to now
let iYears = trunc(dDistance/31536000)
let iMonths = trunc(dDistance/2628000)
let iDays = trunc(dDistance/86400)
let iHours = trunc(dDistance/3600)
let iMinutes = trunc(dDistance/60)
let iSeconds = trunc(dDistance) //Not really needed
var sReturn: String
if iYears >= 2 {
sReturn = iYears.formatted()+" years"
} else if iYears == 1 {
sReturn = "1 year"
} else if iMonths >= 2 {
sReturn = iMonths.formatted()+" months"
} else if iMonths == 1 {
sReturn = "1 month"
} else if iDays >= 2 {
sReturn = iDays.formatted()+" days"
} else if iDays == 1 {
sReturn = "1 day"
} else if iHours >= 2 {
sReturn = iHours.formatted()+" hours"
} else if iHours == 1 {
sReturn = "1 hour"
} else if iMinutes >= 2 {
sReturn = iMinutes.formatted()+" minutes"
} else if iMinutes == 1 {
sReturn = "1 minute"
} else if blIncludeJustNow {
sReturn = "just now"
} else {
sReturn = ""
}
if stAppendString != "" && sReturn != "just now" {
sReturn += stAppendString
}
return sReturn
}
}
I’ve written the above code, but it doesn’t feel particularly efficient. Are there some functions or shortcuts I’m missing?
2
Answers
You’re right, that code is a bit lengthy. Here’s a cleaner and more efficient approach using Swift’s DateComponentsFormatter:
Sweeper already told you the solution in a comment, but it needs to be logged as an answer.
You want
RelativeDateTimeFormatter
. The docs describe it as "A formatter that creates locale-aware string representations of a relative date or time."This code:
Generates output like this: