-1

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

matt
  • 515,959
  • 87
  • 875
  • 1,141
Swift Developer
  • 247
  • 2
  • 18

2 Answers2

6

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") // "تسعة عشر ثلاثة و ثلاثون"
Grimxn
  • 22,115
  • 10
  • 72
  • 85
  • Building on this code. What if you added `let langStr = Locale.current.languageCode` and then you could have `spell(hour, langStr!) + " " + spell(minutes, langStr!)`? Which would handle passing the language code. – MwcsMac Feb 20 '17 at 20:02
  • Sure - or (as your code does) you could ignore the locale, and it would default to `Locale.current`! I just added it to clarify that locale is important, whether specified or defaulted... – Grimxn Feb 20 '17 at 20:07
3

This code will show you that it is possible to achieve the end goal. Keep in mind as stated above you will need create the logic for combinations that you want achieve.

Swift 3

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)

func spell(_ number: Int) -> String {
    let formatter = NumberFormatter()
    formatter.numberStyle = .spellOut // This will convert the number to words.
    return formatter.string(from: NSNumber(value: number))!
}

if minutes == 30 {
    let hourString = spell(hour)
    print("It's half past \(hourString)")
} 

This could be a way that you would use a range for the time frames.

if case 1 ... 14 = minutes {
     let hourString = spell(hour) // This will give your hour in word form
     let minString = spell(minutes) // This will give your minutes in word form
     print("It's \(minString) past \(hourString)")
}
Grimxn
  • 22,115
  • 10
  • 72
  • 85
MwcsMac
  • 6,810
  • 5
  • 32
  • 52
  • This is a useful answer, but you really need to tidy it up. What does `let numberAsNumber = Int(number)` do when `number` is an `Int` already? Why the spurious `let formatter = ` in the `if` clause? What happens if `minutes <= 30`??? And please *comment* what you're doing! – Grimxn Feb 20 '17 at 18:18
  • I don't know anyone that considers all of 15 - 29 minutes past an hour to be "quarter past". – rmaddy Feb 20 '17 at 19:13