swiftnsdatecomponentsformatter

Can I use a DateComponentsFormatter to render the time of day?


I would like to store a time of day in a simple way. For the purposes of my app, I only care about a specific time of day, like 2:30pm or 1:10am.

Using a DateComponentsFormatter I can get really close.

import Foundation

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.allowedUnits = [
    .hour,
    .minute
]
 
// Use the configured formatter to generate the string.
let timeAmount = 9000.0
let outputString = formatter.string(from: timeAmount)
let desiredString = "2:30 pm"import Foundation

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.allowedUnits = [
    .hour,
    .minute
]
 
// Use the configured formatter to generate the string.
let timeAmount = 9000.0
let outputString = formatter.string(from: timeAmount) // yields "2:30"
let desiredString = "2:30 pm"

Now, it seems that the formatter is really just saying "two hours and thirty minutes," so maybe I am barking up the wrong tree here. Does DateComponentsFormatter support my use case?


Solution

  • The DateComponentsFormatter is for expressing the amount of time between two dates. DateFormatter is for formatting dates or times. Use DateFormatter.

    If your intent is to display a time in the UI, use DateFormatter, but

    E.g. to show the current time in the UI:

    let date = Date()
    let formatter = DateFormatter()
    formatter.timeStyle = .short
    let string = formatter.string(from: date)
    

    By the way, this will format time strings as preferred by the user (e.g. AM/PM for some of us, but in other locales, users may prefer 24 hour clock representation). When displaying information in the UI, we should always honor the user’s preferences.


    If you’re trying to convert your 9,000 seconds to 2:30am:

    let startOfDay = Calendar.current.startOfDay(for: Date())
    let date = startOfDay.addingTimeInterval(9000)
    
    let formatter = DateFormatter()
    formatter.timeStyle = .short
    let string = formatter.string(from: date)    // 2:30 AM
    

    Clearly, if you happen to be on a date where you are shifting to or from daylight savings, your result may vary.