Search code examples
swiftfoundation

How to express current time in words


I am able to get current time, Now I want to output it in words.

let date = Date()
let calendar = Calendar.current
let hour = calendar.component(.hour, from: date)
let minutes = calendar.component(.minute, from: date)
let seconds = calendar.component(.second, from: date)
print("hours = \(hour):\(minutes):\(seconds)")

Output

10:30

How to get this like -

It's half past ten


Solution

  • As @MwcsMac points out in his answer, the key to solving this is Formatter (once known as NSFormatter), particularly by setting the .numberStyle to .spellOut.

    Although this will pick up the current locale (and thus language), the trouble is that many other languages than English do not use the same "half-past", "quarter-to" terminology - for example, in German 10:30 is "halb elf", literally "half (to) eleven".

    Writing code that assumes that the locale is English/American is really bad practice and will probably get the app rejected if it is offered outside those areas, so the best one could really do is format "10:30" as "ten thirty", "zehn dreißig".

    Code with apologies to @MwcsMac:

    import Foundation
    
    let date = Date()
    let calendar = Calendar.current
    let hour = calendar.component(.hour, from: date)
    let minute = calendar.component(.minute, from: date)
    
    func spell(_ number: Int, _ localeID: String) -> String {
        let formatter = NumberFormatter()
        formatter.numberStyle = .spellOut
        // Specify the locale or you will inherit the current default locale
        formatter.locale = Locale(identifier: localeID)
        if let s = formatter.string(from: NSNumber(value: number)) {
            // AVOID forced unwrapping at all times!
            return s
        } else {
            return "<Invalid>" // or make return optional and return `nil`
        }
    }
    spell(hour, "EN") + " " + spell(minute, "EN") // "nineteen thirty-three"
    spell(hour, "FR") + " " + spell(minute, "FR") // ""dix-neuf trente-trois"
    spell(hour, "AR") + " " + spell(minute, "AR") // "تسعة عشر ثلاثة و ثلاثون"