Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can DateComponentsFormatter format fractional seconds?

I want to print, e.g., the value 1.5 as "1.5 sec", like Safari's timeline does, and I'm trying to use DateComponentsFormatter for it.

Unfortunately, its .allowedUnits only goes down to .second (even though the enum has .nanosecond). I tried setting .allowsFractionalUnits = true, but I'm still getting "0 sec".

Is there any way to get fractional seconds out of DateComponentsFormatter?

like image 434
Ssswift Avatar asked Apr 08 '17 07:04

Ssswift


1 Answers

For positional units style, DateComponentsFormatter can be used together with NumberFormatter to get locale-aware string.

func format(_ seconds: TimeInterval) -> String {
  let components = DateComponentsFormatter()
  components.allowedUnits = [.minute, .second]
  components.allowsFractionalUnits = true // does not work as expected
  components.unitsStyle = .positional
  components.zeroFormattingBehavior = .pad

  let fraction = NumberFormatter()
  fraction.maximumIntegerDigits = 0
  fraction.minimumFractionDigits = 0
  fraction.maximumFractionDigits = 3
  fraction.alwaysShowsDecimalSeparator = false

  let fractionalPart = NSNumber(value: seconds.truncatingRemainder(dividingBy: 1))

  return components.string(from: seconds)! + fraction.string(from: fractionalPart)!
}

print(Locale.current) // ru_RU (current)
print(format(600.5))  // 10:00,5 <- note locale specific decimal separator

Unfortunately, using this method for other date styles is even more hacky.

like image 55
nikstar Avatar answered Nov 19 '22 04:11

nikstar