Swift货币格式ISO标准转换问题

4
阅读了Apple NSNumberFormatter的文档这里后,我正试图按照Uber API文档将货币进行转换。两个文档都声明使用ISO格式标准,但在我的代码中,我发现这并不是事实。ISO 4217标准在这里,以及ISO 本身
public static func convertStringCurrencyToNumber(strCurrency:String, locale:String)->Double {
    var formatter = NSNumberFormatter()
    formatter.locale = NSLocale(localeIdentifier: "\(locale)")
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    println(formatter.numberFromString(strCurrency))
    if let converted:Double = formatter.numberFromString(strCurrency)?.doubleValue {
        return converted
    }else{
        return 0.0
    }

}

这个函数的单元测试

func testCurrencyConversion() {
    let fiveBucks = UberReceipt.convertStringCurrencyToNumber("$5.00", locale: "en_US")
    println(fiveBucks)
    let tenBucks = UberReceipt.converStringCurrencyToNumber("$10.00", locale:"USD")
    println(tenBucks)
}

控制台日志: Optional(5.0) nil 5.0 0.0

如果我使用 "en_US",结果如预期的那样是 5.0,但是如果我使用 Uber 返回的语言环境 "USD",返回值为 0.0。在打印/检查格式化程序转换货币时发生了什么之后,我发现它返回 nil。

我发现文档对于 formatter.locale = NSLocale(...) 的说明有误导性。根据文档 "语言环境确定许多格式化程序属性的默认值,例如 ISO 国家和语言代码,货币代码..."

我认为设置语言环境 应该 也会设置货币代码。这是不正确的吗?那么为什么我的代码可以使用非标准的 "en_US" 代码而不是 ISO 代码(苹果文档所使用的代码) "USD" 呢?


1
ISO货币代码是USD。没有地区代码USA。美国的本地代码包括en_US(英语)和es_US(西班牙语)等。如果Uber API正在执行您描述的操作,则是错误的。 - Code Different
即使我犯了一个可怕的错误,将USA替换为USD后,它仍然打印出0.0和“nil”进行格式转换,“en_US”仍然完美地工作。Uber API确实返回USD,但显然我无法阅读,我的思维自动将其转化为USA。然而,我的代码仍然存在问题,我不确定为什么它不接受USD作为区域设置字符串。 - TimD
2个回答

5
public static func convertStringCurrencyToNumber(strCurrency:String, locale:String)->Double {
    var formatter = NSNumberFormatter()
    formatter.currencyCode = locale
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    if let converted:Double = formatter.numberFromString(strCurrency)?.doubleValue {
        return converted
    }else{
        return 0.0
    }
}

将 formatter.locale 改为 formatter.currencyCode 对于 ISO 4127 国家和货币代码“USD”可以如预期地起作用。

0

正如Zoff Dino所说,USD不是有效的区域设置标识符。要获取完整列表,可以运行:

NSLocale.availableLocaleIdentifiers() 

你说得对,设置区域设置会设置货币代码。例如,尝试使用以下代码:

let l = NSLocale(localeIdentifier: "de_CH")
let f = NSNumberFormatter()
f.locale = l
f.currencyCode // Playground shows CHF

Locale 定义了正确的字母顺序、千位分隔符、时间和日期格式、货币代码以及其他内容。您传递的不是区域设置,而是货币代码。如果您想从货币代码构建区域设置,可以从 NSLocale.availableLocaleIdentifiers() 的输出和相应的货币代码创建查找表。

如果您澄清 API 返回的内容以及您想要执行的确切操作,可能会有所帮助。


我觉得我没有表达清楚我的意思。我希望有一个函数,它接受格式为"$4.00"或任何有效货币字符串和使用ISO 4217 3字符代码的区域设置的字符串。例如:func example(currency:String, locale:String)。示例:func example("$4.00", "USD")。USD是ISO 4217中有效的区域设置。我认为苹果文档在要求将其设置为"en_US"时存在误导性,而"en_US"实际上是"USD"的缩写。我的修订问题是,区域设置是否能够识别标准的三位国家和货币代码? - TimD
此外,我认为使用“en_US”作为区域标识符是具有误导性的。在ISO 8859-15中定义的“en_US”是“8位单字节编码图形字符集”。对我来说,这定义了可用的字符代码。 “$”是该字符集的一部分。但再次强调,这是具有误导性的,特别是因为Apple文档提到ISO 4217作为println(f.currencyCode)的输出。 - TimD
我认为你把地区设置和货币代码混淆了。请参考https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/index.html。 - MirekE
我想我是。但问题仍然存在,“en_US”定义了一个8位字符集。文档上的措辞可能不太直观。无论如何,我将尝试仅设置货币代码,并查看其在AM中是否有效,并发布结果。https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/index.html#//apple_ref/occ/instp/NSNumberFormatter/currencyCode - TimD
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接