swiftswiftuidateformatter

Using a NumberFormatter within a DateFormatter


I'm attempting to format my Date() to look like Saturday, June 12th • 5PM - 12PM. I've been able to solve the majority of this with the following DateFormatter():

var date_formatter: DateFormatter {
    let formatter = DateFormatter()
    formatter.dateFormat = "EEEE, MMMM d • HHa - HHa"
    return formatter
}

Which results in Saturday, June 12 • 5PM - 12PM

The challenge I'm having is understanding how to add the ordinal suffix (i.e. 12 -> 12th). I've seen a bit on the NumberFormatter(), but am not entirely sure how to integrate the two.

EDIT: Ended up having to create two formats for the 5PM - 12PM logic.

This looks like:

var start_time_formatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateFormat = "EEEE, MMMM d • HHa -"
        return formatter
    }

    var end_time_formatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateFormat = "HHa"
        return formatter
    }

with the following to display it in a view:

Text("\(self.create_event_vm.start_time, formatter: self.start_time_formatter) \(self.create_event_vm.end_time, formatter: self.end_time_formatter)")

I understand this is a bit funky and could use some refactoring, but I'm hoping to get the desired effect, test, then refactor.


Solution

  • First for the day suffix you can create below function

    func getDaySuffix(from date: Date) -> String {  
        switch Calendar.current.component(.day, from: date) {
        case 1, 21, 31: return "st"
        case 2, 22: return "nd"
        case 3, 23: return "rd"
        default: return "th"
        }
    }
    

    and combine with your codes :

    let startDate = Date()
    let endDate = Calendar.current.date(byAdding: .hour, value: 5, to: startDate)!
    
    var startTimeFormatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "EEEE, MMMM d'\(getDaySuffix(from: startDate))' • ha - "
        return formatter
    }
    
    var endTimeFormatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "ha"
        return formatter
    }
    
    let startDateResult = startTimeFormatter.string(from: startDate) // "Thursday, June 18th • 2AM - "
    let endDateResult = endTimeFormatter.string(from: endDate) // "7AM"
    let finalResult = startDateResult + endDateResult // "Thursday, June 18th • 2AM - 7AM"