Reputation: 62674
How do I get a string into a 'currency' format USD(xxx)? I am trying to use the following library: https://github.com/peek-travel/swift-currency
I want to be able to take a string:
var testStr1 = "$30.01"
var testStr2 = "$ 30.01"
and convert this into a currency as I have read from several posts using a double or float is bad, but if I start with a String, what else can I convert it to?
I thought I could use the "import Currency" library to do this, but this is not working.
let updatedString = testStr1.replacingOccurrences(of: "$", with: "")
let formatter = NumberFormatter()
formatter.locale = Locale.current // USA: Locale(identifier: "en_US")
formatter.numberStyle = .decimal
let number = formatter.number(from: test)
var dollars = USD(updatedString)
How do I get a string into a 'currency' format USD(xxx)? If there is a better way to accomplish this?
Upvotes: 0
Views: 253
Reputation: 347314
The basic concept presented by Himanshu works fine, but your problem isn't necessarily making use of an appropriate formatter, but how to fix your input, as the formatter expects a NSNumber
and not a String
.
So a quick internet check had me looking at Remove all non-numeric characters from a string in swift
So I could take a String
, filter out all the "non numerical" junk and then make a Double
out of it.
let input = Double(value.filter("0123456789.".contains))
from there I was able to borrow the concept from Himanshu and make a simple format
function
func format(_ value: String, locale: Locale = Locale.current) -> String? {
guard let input = Double(value.filter("0123456789.".contains)) else { return nil }
//value.trimmingCharacters(in: .whitespacesAndNewlines)
let currencyFormatter = NumberFormatter()
currencyFormatter.usesGroupingSeparator = true
currencyFormatter.numberStyle = .currency
currencyFormatter.locale = locale
return currencyFormatter.string(from: NSNumber(value: input))
}
I then made use of a Playground to test it using
var testStr1 = "$30.01"
var testStr2 = "$ 30.01"
format(testStr1, locale: Locale(identifier: "en_US")) // $30.01
format(testStr2, locale: Locale(identifier: "en_US")) // $30.01
format(testStr1, locale: Locale(identifier: "fr_FR")) // 30,01 €
format(testStr2, locale: Locale(identifier: "fr_FR")) // 30,01 €
format(testStr1, locale: Locale(identifier: "de_DE")) // 30,01 €
format(testStr2, locale: Locale(identifier: "de_DE")) // 30,01 €
Now, if you specifically want to use USD(xxx)
as the format, then you could simply use a basic NumberFormatter
and generate your own String
from the resulting conversion of the input to a Double
I have read from several posts using a double or float is bad
So, yes, maintaining a currency value as a Double
or Float
is generally a bad idea, currency values are typically maintained as a Int
or Long
, but this is due to how Double
and Float
representation works in computers, for the, general, presentation, you should be fine, but each use case needs be assessed.
Upvotes: 2
Reputation: 1033
let currencyFormatter = NumberFormatter()
currencyFormatter.usesGroupingSeparator = true
currencyFormatter.numberStyle = .currency
// localize to your grouping and decimal separator
currencyFormatter.locale = Locale.current
// We'll force unwrap with the !, if you've got defined data you may need more
error checking
let priceString = currencyFormatter.string(from: 9999.99)!
print(priceString) // Displays $9,999.99 in the US locale
**Forcing a Custom Locale**
You can override the users locale to display specific currency formats by changing the Locale using the identifier.
currencyFormatter.locale = Locale(identifier: "fr_FR")
if let priceString = currencyFormatter.string(from: 9999.99) {
print(priceString) // Displays 9 999,99 € in the French locale
}
currencyFormatter.locale = Locale(identifier: "de_DE")
if let priceString = currencyFormatter.string(from: 9999.99) {
print(priceString) // Displays 9.999,99 € in the German locale
}
Upvotes: 1