When parsing Euro amounts, amounts that should be valid throw an error
jgrantr opened this issue · 4 comments
Here is a test case that will fail (and shouldn't, unless I am missing something):
#[test]
fn test_rusty_money() {
let eur = Money::from_str("2.00", iso::EUR).unwrap();
}
Euro's are divided into 100 cents (much like the GBP and the USD), and yet the parser is treating an amount like "2.00" or "2.50" as invalid. If I change that line to have 3 digits after the decimal, it magically works, even though "2.00" and "2.000" are the same number. Seems like bug, but perhaps I am missing something.
What I was looking for here is: I have a number that represents a cost and I want to format it as currency. This works fine as long as it is an integer, but without having to re-create stuff, how do I take a generic floating-point number (like 2.5) and represent it as €2,50 or $2.50 or £2.50, etc?
The problem in this case is confusion between the group separator and the decimal separator. Euros use points (.
) as group separator. That's why €2.000
works (and isn't actually the same as €2.00
). To make it work, change your code example to
#[test]
fn test_rusty_money() {
let eur = Money::from_str("2,00", iso::EUR).unwrap();
}
In contrast, GBP and USD use commas (,
) as group separator and the point (.
) as decimal separator, since they use a different locale internally.
@korrat I do not think that the seperators should be a matter of the currency, but a matter of surrounding context.
When I have a ledger and convert from USD to EUR (at a rate of 1:1 for simplicity) going from 1.00 USD to 1,00 EUR is just weird and confusing.
If though within the document punctuation is consistent, its much easier to understand, even for those who are not proficient with each currencies punctuation.
edit
Also the README does not confirm your claim, it shows an example where USD and EUR are parsed from a .
string, and then printed in their localized versions.
use rusty-money::{Money, iso};
let usd = Money::from_str("-2000.009", iso::USD).unwrap();
let eur = Money::from_str("-2000.009", iso::EUR).unwrap();
println!("{}", usd); // -$2,000.01
println!("{}", eur); // -€2.000,01;
@NobbZ, I agree, parsing (and probably also formatting) should be independent of the currency.
The right way to go would probably be a locale-aware parser for Decimal
, which rusty_money
can then extend to parse amount strings.
Also, my previous statement was an oversimplification of the issue from my German-speaking perspective. There are at least 4 different ways in use today to format an amount in euros. I imagine that similar problems also affect other currencies.
Note that with the current version of rusty_money
that README example runs fine, but the final line prints -€2.000.009,00
, which is in line with using .
for grouping.