Ssswift
Ssswift

Reputation: 1027

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?

Upvotes: 16

Views: 908

Answers (1)

nikstar
nikstar

Reputation: 51

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.

Upvotes: 2

Related Questions