Different formatting on different computers when using the same CultureInfo, why? - c#

I'm having an issue when using CultureInfo.
This is basically my code:
Console.WriteLine(0.5.ToString("P2", new CultureInfo("en-US")));
When running it, this is what I get on two different computers:
As you can notice, the formatting isn't the same. The Australia VPS ( running Windows Server 2016) having a space before the percent symbol compared to my computer (Windows 10).
Why that? How can I "really" use the same CultureInfo/formatting everywhere?

The CultureInfo on Windows uses machine/user level locale information and does not have any information on its own. This information is updated relatively frequently by OS versions and updates. As result machines with different levels of patches or different versions of OS will likely have differences, usually minor as you see but sometime critical if something like decimal separator changes between '.' and ',' or currency symbol for a region changes.
Usually it is not a problem as such formatting is used only to show/parse values from the user and not to store data anywhere (which uses InvariantCulture). Most individual users would not ever use enough machines to notice difference in desktop apps. And for server side code (i.e. ASP.Net) running multiple servers with different versions of OS is even less likely.
If you really must show identical formats independent of OS you would have to build your own CultureInfo objects for locales you interested in. In many cases you can just create your own CultureInfo based on existing one and just patch properties you care about.

Related

CultureInfo("ar") returns English on server

Running this code should yield the Arabic representation of current month and it does on my local machine, however when running on server I always get English.
new CultureInfo("ar").DateTimeFormat.AbbreviatedMonthNames[System.DateTime.Now.Month]
At first I suspected it has something to do with request localization hence I tried to just new up a new culture info and see what it outputs, so the above code returns English regardless.
Set of supported cultures is OS specific - you get different sets even between flavors of Windows - desktop and server editions are different, generally with server having less supported cultures. Also the older version of Windows you use smaller list of cultures is supported. The same applies to running .NET core on other OS (including Linux in Kubernetes containers) - it's OS that essentially drives list of supported cultures.
Note that some OS (Windows 10 in particular) will happily provide you with "culture info" for any string you pass - it will try the best to construct something that may make sense (i.e. for "ru-GB" it may try to give "en-GB" culture as the closest one), but for something that has no information whatsoever you likely get invariant/neutral culture (which generally resembles en-US).

CultureInfo nb-NO DateTime.TryParse difference in VS2019 and on dotnetfiddle.net

On my machine when I run and output the following
string locale = "nb-NO";
CultureInfo culture = CultureInfo.CreateSpecificCulture(locale);
string shortDateFormatString = culture.DateTimeFormat.ShortDatePattern;
string shortTimeFormatString = culture.DateTimeFormat.ShortTimePattern;
I got the following output
shortDateFormatString "dd.MM.yyyy"
ShortTimePattern "HH:mm"
But on dotnetfiddle.net I got the following
shortDateFormatString "dd.MM.yyyy"
ShortTimePattern "HH.mm"
I suppose C# uses CLDR, so according to
https://github.com/unicode-cldr/cldr-dates-full/blob/1af902b749bef761f07281f80241250053b4313d/main/nb/ca-gregorian.json#L323
Both short time pattern should be valid.
And on dotnetfiddle it is possible to parse nb-NO datetime looking as following
06.12.2017 12:34
06.12.2017 12.34
However in VS2019 on my machine it is only possible to parse
06.12.2017 12:34
How is it possible it is different? both is using .NET 4.7.2.
You can check my fiddle here https://dotnetfiddle.net/68DDYz
How is it possible it is different?
Because culture information is loaded from the operating system, and changes over time. Unless two machines are on the exact same version of Windows (same set of updates, hotfixes etc), it's entirely possible for them to have different values for things like short time patterns. (And yes, that's annoying, but it's part of life.)
Jon is quite right (duh!)
Culture settings are tricky. Since they are stored on the windows registry, they can be different/change over .net framework versions, operating system versions, windows updates, hotfixes etc. That means even if both server uses same .NET Framework version, that doesn't mean that every culture settings will be same for both.
I can show you the it-IT culture for example.
See: .NET (3.5) formats times using dots instead of colons as TimeSeparator for it-IT culture?
For .NET Framework 3.5, it-IT culture has . as a TimeSeparator but with .NET Framework 4.0 version, it changed to : which is stated on Wikipedia.
This changes are not end of the world of course, but it was not pleasant either.

c# how can I read String of double correctly despite the number Format?

Hi guys my problem is this. I made a software in c# that is able to read and edit dxf files, I have to give this software to an american company but I have discovered the following problem:
Where I live we use the ',' to separate the integer part from the decimal part of the number (for example: 2,3658) but in the USA they use the '.' so they write 2.3658.
When I try to read the string "2.3658" and convert it into a double with "Double.Parse("2.3658")" the double I get is 23658 like the method "Parse()" didn't recognised the decimal part.
I have found the following solution:
UpdatedCoorx = double.Parse(shiftedE[w + 1] ,NumberStyles.Number,CultureInfo.CreateSpecificCulture ("en-US"));
Using CultureInfo.CreateSpecificCulture ("en-US") the c# can read the numbers correctly.
My question is : is there a way that make c# automatically recognised the "Culture" of the pc where is installed so that it can read the number correctly???
is there a way that make c# automatically recognised the "Culture" of the pc where is installed so that it can read the number correctly?
That's what it's doing by default - and why you're having a problem, because the culture used to created of the value you're parsing ("2.3658") isn't the culture on your local machine.
For any particular value, you should really know which culture produced it. For machine-to-machine communication, it's best to use the invariant culture (CultureInfo.Invariant) which is mostly similar to the US. Ideally, you shouldn't store values in a culture-specific format at all; either store them in a binary representation instead of a string, or if you must store a string, treat that as effectively machine-to-machine communication.
If you're in the unfortunate position of receiving data where you know it's been formatted according to some human culture, but you don't know which one, you should probably use some heuristics to detect what the culture is. That can easily fail though - for example, is "1,234" meant to be a 1 followed by a "grouping" separator, followed by 234 - meaning one thousand, two hundred and thirty-four... or is it meant to be a 1 followed by a decimal separator, making the value just a bit more than 1? Both interpretations are valid, depending on the culture you use...
If you want to detect the Culture, you should be able to do so with this
As explained in the link CultureInfo.CurrentCulture returns the Culture from the Windows GetUserDefaultLocaleName function.
Jon's answer is pretty spot on (as usual). I just wanted to add that if you are developing an application that will be used by people in another country, it may be helpful for you to use CultureInfo.DefaultThreadCurrentUICulture while you are in development mode: just assign your users' culture to this property when the application starts, and you will have exactly the same usage experience (culture-related-things-wise) that your users will have. (Just remember to remove this when you ship your application! You could for example use a #if debug block)

Best practices when working with currencies

I'm working on a desktop application that may potentially be deployed world-wide. My biggest issue with internationalization is currencies. A couple questions:
I'm using SQL Server Compact Edition, which supports the MONEY type. My first question is will this handle data storage regardless of the user's culture?
My second question is data processing. I know I can use the "C" format string, and I guess that's all right for displaying, but when saving back how do I handle user-entered values? Is there a standard way to parse the entered value and save it to the MONEY field, all while being culture-aware and not having to write for any kind of exceptions?
I'm working with C# in WPF, but I'm guessing there is probably a near-universal solution to all this.
The MONEY type just tells the system to use the required accuracy and rounding rules required to handle monetary calculations properly. It doesn't know anything about the actual currency. You need to handle that in the UI and with currency conversion rules.
The framework uses the current culture to display the correct currency symbol for monetary string formats, but if you are displaying different currencies you'll need to override this behaviour.
With C#/WPF (and Silverlight) if you output the currency using the StringFormat in XAML then it handles the user input as well (or at least it has in my experience).

Collecting useful server information

I want to add a page to an existing website with a list of practical system information about the server that's running the site. For example, which windows version, 32 or 64 bits, SQL Server version, some host variables, amount of RAM, disk space and whatever else. Basically, anything practical that could tell me more about the health of the server.
So, how do I get the most practical information through .NET?
Not important how it's going to be displayed but assume it's a list with three columns: Name of the setting, value for the setting and a description that tells what the setting is for... (The first two would already be enough, though, but for clarifications a description would be nice.)
One added complication, though: I need both 32-bits and 64-bits solutions...
Use WMI counters:
http://msdn.microsoft.com/en-us/library/bb404655.aspx
EDIT:
See this questions for examples
How can I check for available disk space?
have a look on this url
http://msdn.microsoft.com/en-us/library/system.environment.osversion.aspx
and Request.ServerVariables Collection
e.g.
Request.ServerVariables[""];
The best way to do this is using SNMP performance counters. This basically allows you to (through IIS) interact with system performance information.
Here is a list of performance counters
And here is a cool tutorial on how to use them

Categories

Resources