String formating unexpected result - c#

Why are these 2 lines show different values? Is it because {0:18}"? Why? Thanks.
Console.WriteLine(value.ToString("C", CultureInfo.GetCultureInfo("da-DK"))); //-12,46 kr.
Console.WriteLine("{0,-18}",value.ToString("C"), CultureInfo.GetCultureInfo("da-DK")); //($12.46)

Is it because {0:18}?
No. In the first case, you're formatting your value as string a using the "C" format specifier, and using the Danish culture.
In the second case, you're formatting your value as string a using the "C" format specifier using the default culture... and then including that string value in another format operation. You're passing the Danish culture as a second, unused format argument, but even if you passed it in the right place, it would be irrelevant by that point, as when you format a string, it always just stays as it is, regardless of culture.
I suspect you actually want this:
string text = value.ToString("C", CultureInfo.GetCultureInfo("da-DK"));
Console.WriteLine("{0,-18}", text);
Or to do all the string formatting in one operation:
string text = string.Format(CultureInfo.GetCultureInfo("da-DK"), "{0,-18:C}", value);
Console.WriteLine(text);
(As far as I can tell, Console.WriteLine has no overload permitting the culture to be specified.)

The culture parameter treats differently in these calls; for the 1st fragment
Console.WriteLine(value.ToString("C", CultureInfo.GetCultureInfo("da-DK")));
we have value converted to string treating value as being currency ("C") of Danemark (CultureInfo.GetCultureInfo("da-DK")). On the contrary for
Console.WriteLine("{0,-18}",value.ToString("C"), CultureInfo.GetCultureInfo("da-DK"));
we have efficiently String.Format ("{0,-18}") call with two parameters:
value.ToString("C") - value as default culture (not necessary da-DK) currency, so it can be, say, "15.47$"
CultureInfo.GetCultureInfo("da-DK") which is ignored (no {1} in the format)

Related

Using invariant culture with IFormatProvider in DateTime.ParseExact

In the First overload of ParseExact method
public static DateTime ParseExact (string s, string format, IFormatProvider provider);
according to Microsoft:
If format is a custom format pattern that does not include date or time separators (such as "yyyyMMddHHmm"), use the invariant culture for the provider parameter and the widest form of each custom format specifier. For example, if you want to specify hours in the format pattern, specify the wider form, "HH", instead of the narrower form, "H".
In particular if we use stander format pattern we could use any other cultures
what is the really purpose of using invariant culture and widest custom specifier if we use custom format pattern that does not include date or time separators if we use?
The purpose of InvariantCulture is to have a well-known way to format dates and numbers, that does not depend on the system or user locale.
You should use it every time you format something that is not meant to be parsed by humans. For example in a JSON or XML file you want to store the date in ISO format so there is no ambiguity. On the other hand if you display the date on the screen, you generally respect the user's choice of culture and display it in the preferred way.
If you use a custom format, then it would surely be good if the resulting string can be parsed back into the exact same date and time. In order to do that without separators you have to use fixed length strings for each component.
// omitting CultureInfo.InvariantCulture for brevity
var dt = new DateTime(2018,1,2,3,45,6);
dt.ToString("yyyyMMddHHmmss") // returns "20180102034506"
dt.ToString("yyyyMdHms") // returns "2018123456"
You can easily see that the second one is not unique, i.e. there are other dates which will return the same string. In order to avoid that you use the wider form of each component.
the real purpose of invariant culture is taken taken from a an answer in this question, as it describes it's purpose best:
Not all cultures use the same format for dates and decimal / currency
values.
This will matter for you when you are converting input values (read)
that are stored as strings to DateTime, float, double or decimal. It
will also matter if you try to format the aforementioned data types to
strings (write) for display or storage.
If you know what specific culture that your dates and decimal /
currency values will be in ahead of time, you can use that specific
CultureInfo property (i.e. CultureInfo("en-GB")). For example if you
expect a user input.
The CultureInfo.InvariantCulture property is used if you are
formatting or parsing a string that should be parseable by a piece of
software independent of the user's local settings.
To sum this up, the invariant culture will help with conversions be a string stored to float, decimal or asDateTime, it is here also to help when you are trying to format or parse a string that should be parseable by a piece of software independent of the user's local settings, as the quote said and that is what
widest custom specifier
means by that.

String.Format an integer to use a thousands separator with decimal value in danish culture

I have a string totalPRice which holds a value like this 1147,5
I want two things.
1)round the value so that there is always two digits after ,
2)Implement thousands separator in this string, So that final out put will be some thing like this 1.147,50
I have tried some thing like this
String.Format("{0:0.00}", totalPRice)
It does my first requirement correctly by producing an output 1147,50.
But I am way behind in my second requirement. Can any one tell me how I can achieve this?
Note: In danish culture . stands for , and , stands for .
You can refer to Standard Numeric Format Strings and use
string.Format("{0:N2}", 1234.56)
You may also specify the culture manually, if danish is not your default culture:
var danishCulture = CultureInfo.CreateSpecificCulture("da-DK");
string.Format(danishCulture, "{0:N2}", 1234.56);
see MSDN Reference for CultureInfo
You should create a culture-specific CultureInfo object and use it when converting the number into a string. Also, you can set the default culture for your whole program.
Then, your code will look like this:
// create Dennmark-specific culture settings
CultureInfo danishCulture = new CultureInfo("da");
// format the number so that correct Danish decimal and group separators are used
decimal totalPrice = 1234.5m;
Console.WriteLine(totalPrice.ToString("#,###.##", danishCulture));
Note that . and , in the formatting string are specified opposit as you want. This is because they identify decimal and group separators, and are replaced with the correct culture specific-ones.
Try this:
String.Format("{0:N2}", totalPRice)
Another possibility is to use the ToString(string format) overload.
totalPRice.ToString("N2");
If this is a currency value (money!), then it's better to use the current format specifier 'C' or 'c':
string.Format("{0:C}", 1234.56)
Normally I don't write the number of decimal digits since it comes from the international configuration.
You may way to use a different colture specifier if you don't want to use the default one.
var colture = CultureInfo.CreateSpecificCulture("§§§§§");
string.Format(culture, "{0:C}", 1234.56);
where §§§§§ is the string that identifies the desired colture.
Try this for Price format. Put it under template field instead of BoundField.
<%#(decimal.Parse(Eval("YourDataField").ToString())).ToString("N2")%>

Converting string to decimal: how to handle the decimal separator in different cultures

I need to write decimal value to ms access database, but i have a problem with conversion values to decimal in different cultures. Have a values from file, which separates by commma. I try:
public decimal CSingleCulture (string str)
{
string sep = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
string s = str.Replace(",", sep);
return decimal.Parse(s);
}
if NumberDecimalSeparator = "." then work is good, but if NumberDecimalSeparator = "," problems begin... decimal.Parse(s) always return vlaues separates by dot. In this situation, when inserted into a database error occurs.
The recommended way to deal with this is to store the value as a number rather than a string. Both in the database and in your program. When you do that, your current problem simply never arises.
The only time you deal with numbers in string format is when you display them, or accept user input. In those scenarios you can use the user's culture settings to let them see and use their preferred separator.
Should you ever need to convert between string and number for persistence then you must use culture invariant conversion. This appears to be where you are falling down. I suspect that the file you read has no well-defined format. Make sure that when you read and write the file you use CultureInfo.InvariantCulture. If the file does have a well-defined format that differs from the invariant culture, then use an appropriate specific CultureInfo.
Can't actually understand what is it you're trying to accomplish, and I have to agree with the other answer. But one other thing that's good to know is you can use invariant culture like so:
double.Parse("15.0", CultureInfo.InvariantCulture)
This will always expect dot character to delimit your decimal digits regardless of what is set in current thread's culture.

How to convert string to ToString("#,##0") format

in my application i am update my ui with my label and i want to show the number in #,##0 format.
myClass.getNumberOfFiles return string.
myLabel.Text = myClass.getNumberOfFiles();
Assuming getNumberOfFiles returns a string (which, by its name, it shouldn't) :
myLabel.Text = int.Parse(myClass.getNumberOfFiles()).ToString("#,##0");
I suspect you want the standard "numeric" format specifier, with a precision of 0:
label.Text = GetNumberOfFiles().ToString("N0");
This is after you've fixed your getNumberOfFiles() method to be GetNumberOfFiles() (naming convention) and made it return int or long (a method which is meant to fetch a number should not return a string).
This will use the appropriate grouping for the current culture; if you want a different culture you can specify it as a second argument.
int files;
if (int.TryParse(myClass.getNumberOfFiles(), out files)) {
myLabel.Text = files.ToString("N0");
}
This won't work if you have any formatting in the number already I think. It will work though if on the return of getNumberOfFiles() someone was turning an int into a string. If getNumberOfFiles() is returning a formatted string, you will need to do some different stuff. Below assumes the formatting is in the en-US format coming in and you want to display it in Brazilian Portuguese for example. It is shown in a verbose manner so you know how to plug other cultures in if you need to. If its formatted and doesn't need to change between cultures I don't know why you couldn't just assign the return of getNumberOfFiles() directly to the label's Text property.
int files;
var incomingCulture = CultureInfo.CreateSpecificCulture("en-US");
var outgoingCulture = CultureInfo.CreateSpecificCulture("pt-BR");
if (int.TryParse(myClass.getNumberOfFiles(), NumberStyles.Number, incomingCulture, out files)) {
myLabel.Text = files.ToString("N0", outgoingCulture);
}
That being said I agree with all the others saying it is ridiculous to return a string for an integer. But I know sometimes you don't have the luxury of being able to change it.
I'll also point out that if you use the named format specifiers like "N0", one day a programmer coming behind you will bless you in their heart when they have to globalize your code. This is because every CultureInfo instance has an implementation for each of the named formats, however it is impossible for it to have implementations for custom format specifiers.

comma separated double

Where can I set style in which double is writte by ToString() method ?
I am getting for example 2,2345 while I want to have 2.2345
thanks for ay hints,
bye
double a = 2.2345;
string b = a.ToString(CultureInfo.InvariantCulture);
You need to specify a FormatProvider, ususally as a CultureInfo.
For example:
string s = d1.ToString(System.Globalization.CultureInfo.InvariantCulture);
The Double.ToString() method is overloaded, so you can call it with a couple of different signatures to get the output you want.
In this case, your culture settings are affecting the output of the ToString() function. To get the result that you want, you should call Double.ToString(IFormatProvider), passing in CultureInfo.InvariantCulture:
myDouble.ToString(CultureInfo.InvariantCulture);
This should solve your issue.
For future reference, note that another common version of Double.ToString() is the Double.ToString(String) overload. The String parameter is a numeric format string, either one that is predefined or one that you specify. For example:
myDouble.ToString("format string here");
MSDN has a couple of articles on format strings: Standard Numeric Format Strings and Custom Numeric Format Strings.
If you would want the affect to be on your whole application. This could be set on initialization. Thus, note that this would mean an effective change on ALL cultures.
var culture = new CultureInfo(Thread.CurrentThread.CurrentCulture.Name);
culture.NumberFormat.NumberDecimalSeparator = ".";
Thread.CurrentThread.CurrentCulture = culture;
Then just:
string value = (1002.300).ToString();

Categories