Skip to content

Instantly share code, notes, and snippets.

@williamhjcho
Last active February 4, 2019 12:43
Show Gist options
  • Save williamhjcho/b17a6791dc625a1a759e93c2ed44affd to your computer and use it in GitHub Desktop.
Save williamhjcho/b17a6791dc625a1a759e93c2ed44affd to your computer and use it in GitHub Desktop.
iOS - Currency Formatters Playground
import Foundation
extension Locale {
static var customer = Locale.ptBR
static let enUS = Locale(identifier: "en_US")
static let ptBR = Locale(identifier: "pt_BR")
static let esMX = Locale(identifier: "es_MX")
static let jaJP = Locale(identifier: "ja_JP")
static let frCA = Locale(identifier: "fr_CA")
static let zhCN = Locale(identifier: "zh_CN")
}
class CurrencyFormatter: NumberFormatter {
override init() {
super.init()
numberStyle = .currency
roundingMode = .down // 5.089 -> $5.08 or -5.089 -> -5.08
}
convenience init(locale: Locale) {
self.init()
self.locale = locale
}
convenience init(locale: Locale, currencyCode: String) {
self.init(locale: locale)
self.currencyCode = currencyCode
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
class TaggedCurrencyFormatter: CurrencyFormatter {
let tag: String
var openTag: String { return "<\(tag)>" }
var closeTag: String { return "</\(tag)>" }
override var locale: Locale! {
willSet {
positivePrefix = nil
negativePrefix = nil
positiveSuffix = nil
negativeSuffix = nil
currencyDecimalSeparator = nil
}
didSet {
let hasDecimalSeparator = positiveFormat.contains(".")
if hasDecimalSeparator {
currencyDecimalSeparator = closeTag + currencyDecimalSeparator
} else {
positiveSuffix = positiveSuffix + closeTag
negativeSuffix = negativeSuffix + closeTag
}
}
}
init(tag: String) {
self.tag = tag
super.init()
}
convenience init(tag: String, locale: Locale) {
self.init(tag: tag)
self.locale = locale
}
convenience init(tag: String, locale: Locale, currencyCode: String) {
self.init(tag: tag, locale: locale)
self.currencyCode = currencyCode
}
required init?(coder aDecoder: NSCoder) {
tag = "bold"
super.init(coder: aDecoder)
}
override func string(from number: NSNumber) -> String? {
// When updating both prefixes the final format fails (only partial)
let isPositiveNumber = number.compare(0) != .orderedAscending
let prefixKeyPath: ReferenceWritableKeyPath = isPositiveNumber ?
\CurrencyFormatter.positivePrefix :
\CurrencyFormatter.negativePrefix
self[keyPath: prefixKeyPath] = self[keyPath: prefixKeyPath] + openTag
let result = super.string(from: number)
self[keyPath: prefixKeyPath] = nil
return result
}
}
let sharedFormatter = CurrencyFormatter()
func getFormatter(locale: Locale) -> NumberFormatter {
sharedFormatter.locale = locale
return sharedFormatter
}
let sharedBoldFormatter = TaggedCurrencyFormatter(tag: "bold")
func getBoldFormatter(for locale: Locale) -> NumberFormatter {
sharedBoldFormatter.locale = locale
return sharedBoldFormatter
}
let everyLocale = Locale.availableIdentifiers.lazy.map(Locale.init(identifier:))
let allLocales = [Locale.enUS, .ptBR, .esMX, .zhCN, .frCA, .jaJP]
func all(_ number: NSNumber, locales: [Locale] = allLocales) {
print("Value:", number)
print(locales
.map {
let currencyCode = "USD"
let identifier = $0.identifier + ": "
let formatted = [getFormatter(locale: $0).string(from: number)!,
getBoldFormatter(for: $0).string(from: number)!,
CurrencyFormatter(locale: $0, currencyCode: currencyCode).string(from: number)!,
TaggedCurrencyFormatter(tag: "bold", locale: $0, currencyCode: currencyCode).string(from: number)!]
.joined(separator: "\t | ")
return identifier + formatted
}
.joined(separator: "\n"))
print()
}
all(0)
all(1234567.809)
all(-1234567.809)
//all(123.456)
//all(-123.456)
//all(123.45)
//all(-123.45)
func meta(_ f: NumberFormatter) {
print(f.locale.identifier)
print("formats:", f.positiveFormat, f.negativeFormat)
print("decimal:", f.decimalSeparator, f.currencyDecimalSeparator)
print("group:", f.groupingSeparator, f.currencyGroupingSeparator)
print("positive:", f.positivePrefix, f.positiveSuffix)
print("negative:", f.negativePrefix, f.negativeSuffix)
print()
}
//allLocales.forEach(meta)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment