Convert.ToDouble("4089.90") outputs 40.899,00 why? - c#

I am developing a software that uses number precision, but I have this problem, it happens that when I take a string to convert to double it outputs me with a different culture.
For example I use
Convert.ToDouble("4089.90"); // it outputs 40.899,00
Is strange cause in my computer it works OK but on the client's PC (with the same culture in regional settings) shows me the latter output. I know I can fix it using
Convert.ToDouble("4089.90", System.Globalization.CultureInfo.InvariantCulture);
But there is a lot of code in the program using "Convert.ToDouble" and I wouldn't like to change all of it, on the other hand I want to understand why this happens.

You can set the culture for your thread with:
Thread.CurrentThread.CurrentCulture =
System.Globalization.CultureInfo.InvariantCulture;

You don't say where you are based, but the output is consistent with the current culture being one that has "." as the thousands separator and a decimal comma rather than a decimal point.
However, you state that the culture is the same - which contradicts this. Have you or the client changed (or customised) the "Standards and formats" on the Regional and Language Options? If the setting has been customised it will still read as "English (United Kingdom)" (or where ever) but will produce different results to the default.

I know neither c# nor asp.net, but I think the problem is this: You are performing the operation in a culture where the dot . is the thousands separator and not the decimal separator. The very output you quote is the proof: 40.899,00.
What culture/locale are you working in?

Culture could be based on where the ASP.Net application is running, and not the client PC that is running the browser. While their desktop PC might have similar culture settings, the server may differ.

It is your computer that is not giving the correct answer, not theirs. Your culture states that "4089.90" is the same as 4089900, since the dot (.) is used for separating thousands (and thus there should be three numbers after the dot).
It appears you want to use the dot as a decimal-separator, contrary to your culture settings; so you have to use System.Globalization.CultureInfo.InvariantCulture in your program. Sorry.

Actually is very rare this behaviour cause all the machines have the same culture settings, however I think that the best solution would be to modify the web.config like this:
configuration>
<system.web>
<globalization culture = "es-HN" />
</system.web>
</configuration
And apply the settings for the entire application.
Thanx everyone for your assistance.

Related

Inconsistent DecimalSeparator value

When I apply toString() on a number of type double, I get the string with . as the decimal separator. In one of my projects only, I get , as the decimal separator.
I have not changed CultureInfo data. My CurrentCulture is el-GR in all my projects which is the default system Culture. el-GR uses , as the decimal separator but I have changed this value through Windows Regional Settings to . which is reflected correctly to all my projects except the one in question.
The only difference I can tell is that it is a Web Site and not a usual Visual Studio Project. I do not know if this forces Visual Studio NOT to take into account the local computer NumberFormat exceptions and if/how this can be changed.
The CultureInfo your program use, if you don't explicitly set it somehow in code, is related to Regional Settings of current user.
When running a web project, very likely current user is not you, the one logged in in the computer, but a built-in user IIS uses. see this question and display somehow current user to find out if your problem is actually related to this.
To change regional settings for your (.Net & IIS hosted) web application, you can use different method: web.config of your application, web.config of the whole server, settings for IIS, or even tweak the registry.
Have a look at this thread (and also linked threads you find in the left column) for methods you can use.

CultureInfo("fr-BE") different on Windows 8.1 than before

I set the culture for an .NET web app in order to use specific format for numbers, currency and date:
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-BE");
On an Windows 2008 server machine with IIS 7 I get "d/m/yy" as short date format (what I want).
On my (new) Windows 8.1 pro machine (developer and test) I get "d-m-yy" format for the same CultureInfo..."dash" instead of "slash" separator.
I've checked also in Control Panel -> Region and the settings for French(Belgium) are as mentioned above, different in W2k8 server than in W8.1pro...
The .NET version is 4, which is ok. Invariant culture doesn't help, as far as I need specific culture to display in the UI and the problem was there. It is true, changes came with Windows 8... Finally I used to override some settings for the Thread culture, like the Date Separator:
DateTimeFormatInfo dtfi = Thread.CurrentThread.CurrentCulture.DateTimeFormat; if (dtfi.DateSeparator != "/") dtfi.DateSeparator = "/";
This ensure that slash will be the date separator all the time in the current thread.
Thank you.
Does anybody knows about it? Belgium changed national standards? Or, Microsoft did for them? Any idea?
Thanks.
Thanks for the answers. .NET version is 4, which is ok. Invariant culture doesn't help, as far as I need specific culture to display in the UI and the problem was there. It is true, changes came with Windows 8...
Finally I used to override some settings for the Thread culture, like the Date Separator:
DateTimeFormatInfo dtfi = Thread.CurrentThread.CurrentCulture.DateTimeFormat;
if (dtfi.DateSeparator != "/") dtfi.DateSeparator = "/";
This ensure that slash will be the date separator all the time in the current thread.
Thank you.
I was looking at similar issue for CultureInfo 'en-NZ', as it been changed for the same culture setting in different Windows version, and cause my web service saved different strings for the same CultureInfo, and it turns out it is provided by Windows since .Net Framework 4, and was a combination of Windows and .Net before that.
Lucky for me, I can make use of Invariant culture, which was recommended by Microsoft to make sure the string I saved into Database not going to be changed because of Windows or future .Net Framework update. The thing is, for my case it was the AM\PMDesignator changed from a.m.\p.m. to AM\PM, and the Invariant culture will make sure it saves to AM\PM I assume it will not change in the future, but if I want it save to a.m.\p.m. as it was for older version of Windows, Invariant culture wouldn't be able to do that, I will probably need define my own custom culture or overwrite the current culture as you did.
See the other question about Microsoft specified that CultureInof are subject to change without notice

changing the system time format on windows 7

Well I am looking for a method to change the default windows 7 time format for a system.
So if a system uses like 10PM or 10 AM as default time notation, then i like to change that system to 10:00 or 22:00.
I know how to do it through the GUI, but in my case our software (C#) has to check if time notation is OK and if it is not change it by usage of
C#, registry editing, vbscript, commanline or Powershell, or some specific .exe file
The software we wrote allready makes usage of external progs / languages (vbscript/powershell).
But the problem is so far i have not found a method to do this other then taking over a remote screen.
Perhaps someone knows how to do this ?
The same counts for time zone, and date notation.
You may change the system time format using following code:
RegistryKey rk = Registry.CurrentUser.OpenSubKey(#"Control Panel\International", true);
rk.SetValue("sTimeFormat", "hh:mm:ss"); // HH for 24hrs, hh for 12 hrs
But IMO, this would not be a good practice for an application to change the system user's settings without the consent of the user.
I found this link that shows it being done via vb.net but you would have to translate it. or you could compile this to an exe and run it from a shell. http://www.access-programmers.co.uk/forums/showthread.php?t=152624
The property way to do this in .NET is with code such as the following:
CultureInfo newCultureInfo = (CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
newCultureInfo.DateTimeFormat.ShortDatePattern = shortDateFormat;
newCultureInfo.DateTimeFormat.LongTimePattern = longTimeFormat;
Thread.CurrentThread.CurrentCulture = newCultureInfo;
Regarding the solution using the "Control Panel\International" registry key (sorry, can't comment due to not have a 50 reputation):
This doesn't appear to affect the existing process, only new processes created after changing the registry. And obviously code assuming registry values (i.e. implementation details) could break in a future version of windows.
Also the code should Dispose the RegistryKey object. It would be better written with a using block.
Regarding if you should do this, while it would be unlikely an app would want to change the time date format (maybe an app that's an improved way of setting system info), it would be very reasonable to need to do this in an automated test. It's a common bug for code to depend on the default time/date format, so setting them to non-default values, or testing code with various time/date formats could be a good idea.

Language and Locale settings in .NET Framework 4.0

We have a Winform application that gets some numeric values from a database. This works fine when the users version of windows is English. So number formats are all perfect. However when the same application is opened in Windows 7 with Portuguese as the base language (Portuguese-Brazil), the numbers are all formatted wrong. This is because US English and Portuguese formats for numbers are totally different.
It appears this change has occurred recently in .NET Framework 4.0 since the application was working perfectly when it was built using 2.0 Framework.
Example, the number "THOUSAND" will show up as 1.000,00 which is being interpreted as ONE in the system running the Portuguese version of windows.
English: 1,000.00 = Thousand
Portuguese: 1.000,00 = Thousand
Can someone point me to any resources on how to work around this or what is the correct method to force an application to use database values instead of formatting them to the local users' system? The users are OK with numbers being displayed in the US Format.
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
this will reset the culture, use it at the start of your form/program
or
Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
you can try both as i am not sure which one is gonna work
The format (delimmeters and spaces) of displayed numbers is a matter of their string representation. Decimals are stored in DB or memory without delimeters (obviously), they are just 128bits on your hard disk (roughly saying). The format comes to scope when you try to display them. If your number are stored in DB in correct numeric format, then this should not be a problem.
The problem may occur if somewhere you try to convert a string to number. For instance if you store values in db as string (I hope you dont). In this case you should specify the format provider each time you convert numbers to string and vice versa.
For instance:
decimal.Parse(numberAsString, CultureInfo.InvariantCulture); // 1
decimalNumber.ToString(CultureInfo.InvariantCulture); // 2
reference 1
reference 2

How can I change a Windows user's regional settings/date format?

I use a VB6/COM+ application which outputs date/time values based on the short date settings in the Control Panel, Regional Settings, for the user that runs it. The program that then parses that output has a configurable setting for the date format it expects, and presents in the UI.
e.g. If the regional setting for the user is set to mm/dd/yyyy, and it outputs 06/18/2009, the application expecting "18/06/2009" fails with "String was not recognized as a valid DateTime".
As we usually run this application as a service account, which we have not logged in as interactively to create a profile, we generally set the correct date format and then tick the "Apply all settings to the current user account and the default user profile" option.
I would like to be make the C# configuration utility I have written for this mess to be able to set the date format programmatically for a given user.
Edit
I would like nothing more than to change the code, but do not have the ability to do so at this time.
I also know that what I am asking is a bad thing to do. With regards to "it should be the user's choice" - I am that user, as I create it explicitly for the task; I just want to set the date format by a scripted method, rather than having to do the clicking myself.
This is specifically discouraged by Microsoft. Any solution you may come up with will be a filthy hack that will probably stop working soon.
Think of it this way: who are you to decide those settings? Don't you think that's the user's decision?
Back on topic: find an unambiguous format for the applications to communicate in, such as YYYYMMDD. The application that displays can then simply respect the actual user settings, as it should.
But, since you can't change it, just poke into the registry:
Current user:
HKEY_CURRENT_USER\Control Panel\International
Specific user:
HKEY_USERS\(user SID)\Control Panel\International
Default user:
HKEY_USERS\.DEFAULT\Control Panel\International
sShortDate is probably the value you want to change.
If you are going to modify the profile to suit your needs, why not just ignore the profile settings and hardcode the format you want in your app?
code:
Imports System.Threading
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US", False)
Microsoft.Win32.Registry.SetValue("HKEY_CURRENT_USER\Control Panel\International", "sShortDate", "M/d/yyyy")
While persistently changing a user's culture (regional settings) is to be done cautiously, there are legitimate use cases.
On Windows 8 and Windows Server 2012 and above, Windows PowerShell comes with the
Set-Culture cmdlet, which is the programmatic equivalent of choosing a different region via Control Panel (intl.cpl).
For instance, Set-Culture fr-CA is the equivalent of interactively choosing region French (Canada) for the current user.
Caveat: Mixed cultures such as en-DE (sic) appear not to work as of Windows PowerShell v5.1 - see this answer of mine.
While it won't be fast, it is possible to call PowerShell commands from C#.

Categories

Resources