Nitramk
Nitramk

Reputation: 1572

Currency formatting in .NET

I'm trying to get a grip on how currency formatting works in the .NET framework. As I understand it, Thread.CurrentCulture.NumberFormatInfo.CurrencySymbol contains the local culture's currency symbol.

But as I see it, in the real world there's not a clear 1-to-1 relation between a specific culture and the currency symbol. For instance, I may be located in UK but I bill my invoices in Euro. Or I may live in Iceland and receive invoices from US suppliers in USD. Or I may live in Sweden but my bank account uses Euro. I realize that in some cases you may just want to assume that the local currency is the one to use, but often this isn't the case.

In these cases, would I clone the CultureInfo and set the currency symbol manually on the clone and then use the clone when formatting an amount? Even if the currency symbol is not valid, I think that it would still make sense to use other properties of the NumberFormatInfo, such as CurrencyDecimalSeparator.

Upvotes: 3

Views: 2736

Answers (1)

Dan J
Dan J

Reputation: 16708

Absolutely. I've done it using a technique based on a blog post by Matt Weber. Here's an example that uses your culture's format for currency (decimal places, etc.), but uses the currency symbol and number of decimal places appropriate for a given currency code (so one million Yen in the en-US culture would be formatted as ¥1,000,000).

You can, of course, modify it to pick and choose which properties of the current culture and currency's culture are retained.

public static NumberFormatInfo GetCurrencyFormatProviderSymbolDecimals(string currencyCode)
{
    if (String.IsNullOrWhiteSpace(currencyCode))
        return NumberFormatInfo.CurrentInfo;


    var currencyNumberFormat = (from culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures)
                                let region = new RegionInfo(culture.LCID)
                                where String.Equals(region.ISOCurrencySymbol, currencyCode,
                                                    StringComparison.InvariantCultureIgnoreCase)
                                select culture.NumberFormat).First();

    //Need to Clone() a shallow copy here, because GetInstance() returns a read-only NumberFormatInfo
    var desiredNumberFormat = (NumberFormatInfo)NumberFormatInfo.GetInstance(CultureInfo.CurrentCulture).Clone();
    desiredNumberFormat.CurrencyDecimalDigits = currencyNumberFormat.CurrencyDecimalDigits;
    desiredNumberFormat.CurrencySymbol = currencyNumberFormat.CurrencySymbol;

    return desiredNumberFormat;
}

Upvotes: 6

Related Questions