NumberFormatter和Currency Strings的欧元错误

时间:2017-05-04 03:01:10

标签: ios swift swift3 nsdecimalnumber currency-formatting

我在Swift(String扩展名)中编写了一个函数来获取任何货币字符串,例如" $ 500.00"或" 250,75€",甚至" 500"然后从中返回一个nsdecimalnumber。

不幸的是,当我通过" 250,75€"它命中我的代码的if(nf.number(来自:self)== nil)部分并计算为nil,因此不返回任何内容。只有当您使用逗号添加更改时才会发生这种情况,例如250,75。但是,如果我做了250就行了。它似乎只对欧元这样做。美元工作正常($ 500.00,125.75等)

这是我的代码。有什么想法吗?谢谢你的时间!

extension String{
func toDecimalFromCurrencyString() -> NSDecimalNumber
    {

        let nf = NumberFormatter()
        nf.numberStyle = NumberFormatter.Style.currency
        nf.formatterBehavior = NumberFormatter.Behavior.behavior10_4
        nf.generatesDecimalNumbers = true

        var test = self.replacingOccurrences(of: nf.currencySymbol!, with: "", options: NSString.CompareOptions.literal, range: nil)
        test = test.replacingOccurrences(of: nf.currencyDecimalSeparator!, with: "", options: NSString.CompareOptions.literal, range: nil)
        test = test.replacingOccurrences(of: nf.currencyGroupingSeparator!, with: "", options: NSString.CompareOptions.literal, range: nil)
        let scanner: Scanner = Scanner(string:test)
        let isNumeric = (scanner.scanDecimal(nil) && scanner.isAtEnd)

        //If the string entered isn't numeric (for example ... or $$$, then fail)
        if (self.trimmingCharacters(in: CharacterSet.whitespaces).utf16.count == 0 || (!isNumeric))
        {
            return 0.0
        }
        //If the string contains more than one decimal separator (.), or more than one currency symbol ($), return 0.0
        else if ((self.components(separatedBy: nf.currencyDecimalSeparator!).count-1) > 1 || (self.components(separatedBy: nf.currencySymbol!).count - 1) > 1) {
            return 0.0
        }
        //If the string contains more than one consecutive currency grouping separator (i.e. ,,) then return 0.0
        else if ((components(separatedBy: nf.currencyGroupingSeparator! + nf.currencyGroupingSeparator!).count-1) > 0)
        {
            return 0.0
        }
        else
        {
            if (nf.number(from: self) == nil) {
                return 0.00
            }
            else {
                return nf.number(from: self) as! NSDecimalNumber
            }
        }
    }


}

1 个答案:

答案 0 :(得分:1)

您可以简单地修剪字符串中的所有非数字并使用两个数字格式化程序,一个使用点,另一个使用逗号,并使用链中的nil合并运算符,如下所示:

extension Formatter {
    static let decimalWithDotSeparator: NumberFormatter = {
        let numberFormatter = NumberFormatter()
        numberFormatter.numberStyle = .decimal
        numberFormatter.decimalSeparator = "."
        return numberFormatter
    }()
    static let decimalWithCommaSeparator: NumberFormatter = {
        let numberFormatter = NumberFormatter()
        numberFormatter.numberStyle = .decimal
        numberFormatter.decimalSeparator = ","
        return numberFormatter
    }()
}

extension String {
    var numberFromCurrency: NSDecimalNumber? {
        var string = self
        while let first = string.characters.first, Int("\(first)") == nil {
            string = String(string.characters.dropFirst())
        }
        while let last = string.characters.last, Int("\(last)") == nil {
            string = String(string.characters.dropLast())
        }
        return (Formatter.decimalWithDotSeparator.number(from: string) ??
                Formatter.decimalWithCommaSeparator.number(from: string) ?? 0)
                .decimalValue.decimalNumber
    }
}

extension Decimal {
    var decimalNumber: NSDecimalNumber { return NSDecimalNumber(decimal: self) }
}
let dollar = "$249.99"
dollar.numberFromCurrency   // 249.99

let real = "R$249,99"
real.numberFromCurrency   // 249.99

let euro = "0,50€"
euro.numberFromCurrency    // 0.5