DateComponentsFormatter: Format 30 days to one month

Is it possible to convince the DateComponentsFormatter that 30 days are also one month as 31 days are?


The backend to which our app is connected to sends a duration of 30 days and this should be displayed as "1 month" duration on the UI.


This is the code I used:

let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.second, .minute, .hour, .day, .weekOfMonth, .month, .year]
formatter.unitsStyle = .full
formatter.maximumUnitCount = 1
formatter.string(from: duration)

And this will be formatted to "4 weeks" when the duration is 30 days and formatted to "1 month" when duration is 31 days.

I would simply do this:


var adaptedDuration = duration
if duration > 28*86400 && duration <= 31*86400 {
    adaptedDuration = 31*86400
}
// Use now adaptedDuration

Even though that was not through convincing DateFormatter to change its behavior, did this solve the issue ?

If not, what's the problem ?

If yes, don't forget to close the thread.


You could approach what you want with an extension:


extension DateComponentsFormatter {
    func monthString(from ti: TimeInterval) -> String? {
        var adaptedDuration = ti
        if ti > 28*86400 && ti <= 31*86400 {
            adaptedDuration = 31*86400
        }
        return self.string(from: adaptedDuration)
    }
}


Testing:

let duration : Double = 30*86400
print("string", formatter.string(from: duration)!)
print("monthString", formatter.monthString(from: duration)!)

string 4 weeks

monthString 1 month

DateComponentsFormatter: Format 30 days to one month
 
 
Q