I am getting a string value that represents a price. I want to convert it to another string with specific precision and format it according to a current device Locale.
Decimal(string: "123,4567", locale: NSLocale.current)?.formatted(.number.precision(.fractionLength(precision)))
This code works for the german language and the output is "123,45". But if I switch to English the output is "123.00". The problem is with the dot instead of the comma. Any ideas how to fix it and show the correct number "123.45"?
CodePudding user response:
If all you need is to format your decimal number to be displayed using a specific currency what you need is Decimal.FormatStyle.Currency
. It will automatically discard the excess of precision length:
let valueString = "1234,5678"
let decimalLocale: Locale = .init(identifier: "de_DE")
let currencyLocale: Locale = .init(identifier: "en_US") // or current (used US locale just for demonstration purposes)
if let decimal = Decimal(string: valueString, locale: decimalLocale),
let currencyCode = currencyLocale.currencyCode {
let currencyStyle: Decimal.FormatStyle.Currency = .init(code: currencyCode, locale: currencyLocale)
let currencyFormatted = decimal.formatted(
currencyStyle.rounded(rule: .towardZero)
)
print(currencyFormatted) // "$1,234.56\n"
}
edit/update:
I usually don't like manipulating strings but if your source doesn't have a specific format where sometimes de decimal separator is a comma and sometimes a period you need to replace your string comma with a period before converting it to Decimal:
let valueString = "1234,5678"
let currencyLocale: Locale = .init(identifier: "en_US") // or current (used US locale just for demonstration purposes)
if let decimal = Decimal(string: valueString.replacingOccurrences(of: ",", with: ".")),
let currencyCode = currencyLocale.currencyCode {
let currencyStyle: Decimal.FormatStyle.Currency = .init(code: currencyCode, locale: currencyLocale)
let currencyFormatted = decimal.formatted(
currencyStyle.rounded(rule: .towardZero)
)
print(currencyFormatted) // "$1,234.56\n"
}
CodePudding user response:
The locale used for the input string must match the format of the string, so if it is a German format then use a German locale
let locale = Locale(identifier: "de_DE")
let string = Decimal(string: "123,4567", locale: locale)?
.formatted(.number.precision(.fractionLength(precision)))
This uses Locale.current (Swedish in this example) for the output
123,46
Since this is a price here is a currency example
let string = Decimal(string: "123,4567", locale: .current)?
.formatted(.currency(code: "EUR")
.precision(.fractionLength(2))
.rounded(rule: .down)
.locale(.current))
€123,45