24

This should be an easy problem but...

I need to format a currency for display (string) in C#

The currency in question will have its own rules such as the symbol to use and if that symbol should come before the value (e.g. $ 10) or after (e.g. 10 ₫ which is Vietnamese Dong).

But how the numbers are formatted depends upon the users local, not the currency.

E.g.

1.234,56 ₫ should be displayed to a user in Vietnam but 
1,234.56 ₫ should be displayed to a user in the US

(formatted as code so easy to see difference between , and.)

So code like

Double vietnamTotal = 1234.56;
return vietnamTotal.ToString("c");  

Won't work as it will use the users (or more accuratly CultureInfo.CurrentCulture) locale for format and currency so you would get things like $1,123.56 - right use of , and . but wrong symbol.

Double vietnamTotal = 1234.56;
CultureInfo ci = new CultureInfo(1066); // Vietnam
return vietnameTotal.ToString("c",ci)); 

Would give 1.234,56 ₫ - Right symbol, wrong use of , and . for current user.

This post gives more detail on the right thing to do, but not how to do it.

What obvious method hidden in the framework am I missing?

Christophe
  • 68,716
  • 7
  • 72
  • 138
Ryan
  • 23,871
  • 24
  • 86
  • 132

3 Answers3

31
  • Take the NumberFormatInfo from the user's currency, and clone it
  • Set the CurrencySymbol in the cloned format to the CurrencySymbol of the currency in question
  • If you want the currency position (and some other aspects of the format) to be copied, set CurrencyPositivePattern and CurrencyNegativePattern in the same way.
  • Use the result to format.

For example:

using System;
using System.Globalization;

class Test
{    
    static void Main()
    {
        decimal total = 1234.56m;
        CultureInfo vietnam = new CultureInfo(1066);
        CultureInfo usa = new CultureInfo("en-US");

        NumberFormatInfo nfi = usa.NumberFormat;
        nfi = (NumberFormatInfo) nfi.Clone();
        NumberFormatInfo vnfi = vietnam.NumberFormat;
        nfi.CurrencySymbol = vnfi.CurrencySymbol;
        nfi.CurrencyNegativePattern = vnfi.CurrencyNegativePattern;
        nfi.CurrencyPositivePattern = vnfi.CurrencyPositivePattern;

        Console.WriteLine(total.ToString("c", nfi));
    }
}

Admittedly my console doesn't manage to display the right symbol, but I'm sure that's just due to font issues :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Almost Jon, thanks - however it doesn't get the position of the currency symbol correct (e.g. Vietnam or Spain place the currency symbol after the value). You could argue that the position depends upon the users culture (like decimal separator) but products like Excel and SharePoint do the position based on the currency's culture. – Ryan Jul 01 '09 at 21:03
  • Done - you might want to look at the other currency-related properties, although it sounds like don't want to change the grouping size or symbols. – Jon Skeet Jul 01 '09 at 21:21
  • Well I'll be... Thought I might have had you there! I've been looking for where that was hidden for hours. Currency***Pattern eh? – Ryan Jul 01 '09 at 21:28
  • I'm not sure I understand why you're changing the patterns. Surely taking the current culture number info (or clone thereof) and setting the currency symbol is enough ? – Black Light Nov 11 '11 at 12:54
  • @RossWatson: As I mentioned in my answer, if you want the *position* of the currency symbol to be taken into account, you need to copy the pattern. In some cases you may want to do that, in some cases you may not. Note that I'm not setting the *whole* `NumberFormatInfo` into the new format; just the bits that I want. In particular, as per the question we *don't* want to change the decimal / grouping separators. – Jon Skeet Nov 11 '11 at 12:56
  • Hi Jon, why are you cloning NumberFormat? That doesn't seem necessary? Cheers – fearofawhackplanet Jul 12 '16 at 12:29
  • @fearofawhackplanet: It guarantees that it's mutable. It's possible that the one returned by the constructor is mutable as well, but I'm not sure - it seems simplest just to clone, and that means the answer will work in cases where the culture *isn't* mutable (or is going to be used elsewhere). – Jon Skeet Jul 12 '16 at 12:32
1

Sorry, I may be being a little slow here, but I still don't see your point. It seems to me that the original question is "I have a dong value which, in Vietnam, I want displayed as per Vietnamese currency format, with a "₫" symbol, and in the US, I want displayed as per US currency format, but still with a "₫".".

I guess I'm getting confused by the two contradictory statements... "The currency in question will have its own rules" and "how the numbers are formatted depends upon the users local [sic], not the currency."

If all you wanted to change was the currency symbol, and leave the formatting as per the current culture, wouldn't cloning the nfi and setting the symbol be enough ?

     NumberFormatInfo nfi;

     // pretend we're in Vietnam
     Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("vi-VN");

     nfi = CultureInfo.CurrentCulture.NumberFormat.Clone() as NumberFormatInfo;
     nfi.CurrencySymbol = "₫";

     String s1 = (1234.5678).ToString("c", nfi);

     // pretend we're in America
     Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");

     nfi = CultureInfo.CurrentCulture.NumberFormat.Clone() as NumberFormatInfo;
     nfi.CurrencySymbol = "₫";

     String s2 = (1234.5678).ToString("c", nfi);
Black Light
  • 2,358
  • 5
  • 27
  • 49
  • Sorry... seems this ramble was too big for a comment. – Black Light Nov 11 '11 at 13:36
  • Which is exactly what Jon proposed in his answer. – Ryan Nov 15 '11 at 07:52
  • And to the point - if YOU went on a website to see a price for something in Franch would you want to see € 1,234.56 (Euro symbol, US/UK formatting) or € 1.234,56 (Euro symbol and French formatting). – Ryan Nov 15 '11 at 07:53
  • > "Which is exactly what Jon proposed in his answer". Not quite. However, if I was using a machine with a UK culture, I would like a website to show me a Euro and Dollar price as "€1,234.56" and "$1,234.56". If I were using a French culture, I would probably like the website to show me "1 234,57 €" and "1 234,57 $". – Black Light Nov 15 '11 at 14:46
-1

To work with a textbox, try the following:

textBox2.Text = "Rp" + (textBox1.Text = string.Format(System.Globalization.CultureInfo.GetCultureInfo("id-ID"), "{0:#,##0.00}", double.Parse(textBox1.Text)));
nalply
  • 26,770
  • 15
  • 78
  • 101
Kozack Lixeer
  • 19
  • 1
  • 5