# How to create custom \`IntegerFormatStyle\` formatter in Foundation?

**URL:** <https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644>\
**Category:** Using Swift\
**Tags:** foundation, formatter\
**Created:** [June 15, 2021, 1:31pm UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644 "2021-06-15T13:31:54Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![BasemEmara](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/basememara/32/21528_2.png) [@BasemEmara](https://forums.swift.org/u/BasemEmara)\
**Post date:** [June 15, 2021, 1:31pm UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644/1 "2021-06-15T13:31:54Z")

</div>

Is it possible to create custom styles with the [new Foundation formatters](https://developer.apple.com/documentation/foundation/integerformatstyle) that were introduced[in WWDC 2021](https://developer.apple.com/videos/play/wwdc2021/10109/)? Currently, you could format numbers like this:

```swift
print(40.formatted(.percent))
// 40%
    
print(40.formatted(.currency(code: "eur")))
// €40.00
    
print(0.2948485.formatted(.number.precision(.significantDigits(2))))
// 0.29

```

I want to create a new formatter that takes a number and converts to a formatted date component string. It would be great if this is already built in but I could not figure out the correct syntax if it exists. I would like to do something like this:

```swift
print(25.formatted(.number.dateComponent(style: .short, field: .minutes)))
// 25 min

```

For reference, this could be done the "old" way like this:

```swift
static let formatter: DateComponentsFormatter = {
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .short
    formatter.allowedUnits = [.minute]
    return formatter
}()

print(Self.formatter.string(for: DateComponents(minute: 25)))
// 25 min

```

Can this be achieved in Xcode 13 / Swift 5.5 yet?

---

<div class="post-metadata">

**Author:** ![ole](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ole/32/18720_2.png) [@ole](https://forums.swift.org/u/ole)\
**Post date:** [June 18, 2021, 6:52pm UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644/2 "2021-06-18T18:52:45Z")

</div>

You can create your own format styles. Here’s a simple example that reverses the digits of an integer:

```swift
struct ReversedIntegerStyle: FormatStyle {
  typealias FormatInput = Int
  typealias FormatOutput = String

  func format(_ value: Int) -> String {
    String(String(value).reversed())
  }
}

extension FormatStyle where Self == ReversedIntegerStyle {
  static var reversed: ReversedIntegerStyle { .init() }
}

25.formatted(.reversed) // "25"
(-42).formatted(.reversed) // "24-"

```

I haven’t tried to replicate your desired output.

---

<div class="post-metadata">

**Author:** ![BasemEmara](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/basememara/32/21528_2.png) [@BasemEmara](https://forums.swift.org/u/BasemEmara)\
**Post date:** [June 18, 2021, 11:31pm UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644/3 "2021-06-18T23:31:28Z")

</div>

Whoa thanks for the head start!! Below is my attempt in case it helps anyone:

```swift
struct MinuteFormatStyle: FormatStyle {
    let style: DateComponentsFormatter.UnitsStyle

    func format(_ value: Int) -> String? {
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = style
        formatter.allowedUnits = [.minute]

        return formatter.string(for: DateComponents(minute: value))
    }
}

extension FormatStyle where Self == MinuteFormatStyle {
    static func minute(style: DateComponentsFormatter.UnitsStyle) -> Self {
        MinuteFormatStyle(style: style)
    }
}

extension DateComponentsFormatter.UnitsStyle: Codable, Hashable {}

25.formatted(.minute(style: .short)) // "25 mins"

```

Although, there's a lot of things I don't like about my implementation. What intrigued me most about the WWDC session is we no longer have to cache formatters statically which we were forced to do over the years to get around the heavy formatter instantiation. I was hoping this could be leveraged in the API. Maybe that's why `FormatStyle` needs to be `Codable`?, but nothing for certain about this.

---

<div class="post-metadata">

**Author:** ![young](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/young/32/7878_2.png) [@young](https://forums.swift.org/u/young)\
**Post date:** [June 19, 2021, 4:14am UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644/4 "2021-06-19T04:14:34Z")

</div>

Is it possible to make `ReversedIntegerStyle` generic so it can be use for anything using `String(describing:)`?

Something like this:

```swift
struct ReversedStyle<Subject>: FormatStyle {
// no need for this, can just be inferred
// typealias FormatInput = Subject
// typealias FormatOutput = String

  func format(_ value: Subject) -> String {
      String(String(describing: value).reversed())
  }
}

// works!
25.formatted(ReversedStyle())
(-42).formatted(ReversedStyle())
"abcdefg".formatted(ReversedStyle())
(123.456).formatted(ReversedStyle())

// how to do this for static memeber lookup syntax?
extension FormatStyle where Self == ReversedStyle<???> {
    static var reversed: ReversedStyle<???> { .init() }
}

25.formatted(.reversed)
(-42).formatted(.reversed)

```

I get it to work:

```swift
extension FormatStyle where Self == ReversedStyle<Any> {
    static func reversed<Subject>() -> ReversedStyle<Subject> { .init() }
}

25.formatted(.reversed())
(-42).formatted(.reversed())

```

`var` can't be generic? I had to make it a `static func`

---

<div class="post-metadata">

**Author:** ![young](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/young/32/7878_2.png) [@young](https://forums.swift.org/u/young)\
**Post date:** [June 19, 2021, 5:44am UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644/5 "2021-06-19T05:44:15Z")

</div>

> [@BasemEmara](#):
>
> there's a lot of things I don't like about my implementation

I thought I heard "we have converted every existing formatters"?

Yes, there is `Date.ComponentsFormatStyle`

```swift
import Foundation

// all FormatStyle implementations:
// https://developer.apple.com/documentation/foundation/formatstyle?language=_5#relationships
// Date.ComponentsFormatStyle
// https://developer.apple.com/documentation/foundation/date/componentsformatstyle?language=_5

let now = Date.now
// why this doesn't work?
(now..<Date(timeInterval: 25 * 60, since: now)).formatted(.components(style: .abbreviated, fields: [.minute]))
// ^^^^^^^ <==== doesn't like this?!
(now..<Date(timeInterval: 25 * 60, since: now)).formatted(Date.ComponentsFormatStyle(style: .abbreviated, fields: [.minute]))
// 25 min

```

---

<div class="post-metadata">

**Author:** ![ole](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ole/32/18720_2.png) [@ole](https://forums.swift.org/u/ole)\
**Post date:** [June 21, 2021, 10:42am UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644/6 "2021-06-21T10:42:24Z")

</div>

> [@BasemEmara](#):
>
> Although, there's a lot of things I don't like about my implementation. What intrigued me most about the WWDC session is we no longer have to cache formatters statically which we were forced to do over the years to get around the heavy formatter instantiation. I was hoping this could be leveraged in the API.

I suppose you could store the formatter in a static variable to keep it alive, or even implement some kind of lookup table for different formatter configurations if that’s important for your use case.

(I never know if _instantiating_ or _(re-)configuring_ the formatter is the expensive operation, but I suspect it’s often the latter. If that’s true, just keeping the instance around may not help with performance if your `formatted` implementation regularly reconfigures it.)

---

<div class="post-metadata">

**Author:** ![young](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/young/32/7878_2.png) [@young](https://forums.swift.org/u/young)\
**Post date:** [June 21, 2021, 10:24pm UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644/7 "2021-06-21T22:24:34Z")

</div>

Shouldn’t this be used instead?

[https://developer.apple.com/documentation/foundation/date/componentsformatstyle?language=\_5](https://developer.apple.com/documentation/foundation/date/componentsformatstyle?language=_5)

---

<div class="post-metadata">

**Author:** ![Tony\_Parker](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tony_parker/32/273_2.png) [@Tony\_Parker](https://forums.swift.org/u/Tony_Parker)\
**Post date:** [July 16, 2021, 6:15pm UTC](https://forums.swift.org/t/how-to-create-custom-integerformatstyle-formatter-in-foundation/49644/8 "2021-07-16T18:15:08Z")

</div>

The caching is all internal to the new formatting implementation at this time. Mostly because designing the huge API surface of all the styles themselves was enough of a challenge! Exposing the caches themselves so you can use it in a scenario like this is an interesting idea. I'll file a bug for you.
