Home > database >  Swift show price depends on Locale
Swift show price depends on Locale

Time:03-04

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

  • Related