简体   繁体   中英

IOS SWIFT 4 convert String to Decimal with Locale

In IOS SWIFT 4, I am trying to create a Decimal out of a given String for Money calculations considering the Current Locale (Mainly considering Decimal Separator & GroupingSeparator)

Just tried to use Decimal initialization with Locale, BUT as explains in this link if the string contains a non-numeric character, it just reads up to that character rather than providing nil . So I wouldn't know if the string has successfully converted to Decimal or partially considered. eg In following case if the number string (stringValue) has grouping separator it just reads until up to that character (which is comma). So following code provides answer as 1.

let stringValue: String = "1,200.00"
let decValue: Decimal = Decimal(string: stringValue, locale: Locale(identifier: "en_GB")) // ANSWER - 1

That's the problem with Decimal Initialisation. I can resolve that grouping separator problem with NumberFormatter as follows but decimalValue property in converted NSNumber is providing wrong value.

let stringValue: String = "8.20"
let nf = NumberFormatter()
nf.locale = Locale(identifier: "en_GB")
nf.usesGroupingSeparator = true
nf.numberStyle = NumberFormatter.Style.decimal
if let number = nf.number(from: stringValue)
{
    let decValue: Decimal = number.decimalValue  // ANSWER: 8.199999999999999
}

I have seen this was discussed many places but haven't seen a fully resolved answer. Would like to hear what the best way to convert a given String value to it's Decimal number considering the Locale. (If german / French - group separator is "." and Decimal separator is "," etc)

Try this :

let stringValue: String = "8.20"

let loc = Locale(identifier: "en_GB")

let nf = NumberFormatter()
nf.locale = loc
nf.usesGroupingSeparator = true
nf.numberStyle = .decimal

var decValue: Decimal? = nil

if let _ = nf.number(from: stringValue) {

    var copy = stringValue

    if let sep = loc.groupingSeparator {
        copy = copy.split(separator: Character(sep)).joined()
    }

    decValue = Decimal(string: copy, locale: loc)
}

And you could check the result this way :

decValue.map { print($0) }  //8.2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM