Last active
February 4, 2019 12:43
-
-
Save williamhjcho/b17a6791dc625a1a759e93c2ed44affd to your computer and use it in GitHub Desktop.
iOS - Currency Formatters Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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