skip to Main Content

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"?

2

Answers


  1. 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

    Login or Signup to reply.
  2. 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.56n"
    }
    

    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.56n"
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search