We are experiencing weird behaviour between a web application and windows service when trying to perform a ToString() on a DateTime value.
See the example below.
DateTime parsedReportDate;
reportDate = DateTime.Now.ToString("yyyyMMdd");
reportDateWithSlash = DateTime.Now.ToString("dd/MM/yyyy");
if (DateTime.TryParse(MyDateValue, out parsedReportDate))
{
reportDate = parsedReportDate.ToString("yyyyMMdd");
reportDateWithSlash = parsedReportDate.ToString("dd/MM/yyyy");
}
--reportDateWithSlash on Web Application: 28/03/2017
--reportDateWithSlash on Windows Service: 28-03-2017
The Windows Service calls the same function as the Web Application does, so why is the formatting different then?
The formatting of dates to strings uses a CultureInfo object to know what format to use.
Each Thread has a Thread.CurrentCulture property.
You can find out what CultureInfo the current Thread is set by getting the current Thread using Thread.CurrentThread and then inspecting it's Thread.CurrentCulture property.
public class Program
{
public static void Main()
{
Console.WriteLine(Thread.CurrentThread.CurrentCulture.Name);
}
}
https://dotnetfiddle.net/dsA3VT
Output: en-US
You can set the CultureInfo for the the Thread, or pass it with each call to ToString.
Setting Thread.CultureInfo
You can set the Thread.CultureInfo using the same property as you use to read it.
Thread.CurrentCulture = new CultureInfo("en-gb");
Unfortunately .Net Fiddle doesn't support changing thread properties.
I didn't know this, but bradbury9 pointed out that since .net 4.6 you can set the CultureInfo.CurrentCulture property as well.
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("nl-NL");
Unfortunately .Net Fiddle doesn't support changing the culture this way either.
Passing CultureInfo to ToString
'DateTime.ToString' has overloads which can take an IFormatProvider, and CultureInfo impliments IFormatProvider.
DateTime.Now.ToString(new CultureInfo("en-gb"));
https://dotnetfiddle.net/qkS5HF
public class Program
{
public static void Main()
{
var dateTime = DateTime.Now;
Console.WriteLine(Thread.CurrentThread.CurrentCulture.Name);
Console.WriteLine(dateTime.ToString(CultureInfo.InvariantCulture));
Console.WriteLine(dateTime.ToString(new CultureInfo("en-us")));
}
}
Output:
en-US
03/28/2017 09:43:49
3/28/2017 9:43:49 AM
The problem must come from having different cultures. Using the DateTime.ToString (String, IFormatProvider) overload with the CultureInfo.InvariantCulture property should solve the problem:
DateTime.Now.ToString("dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture);
it may be what is calling the Windows service is formatting the date. the code certainly is clear enough. Try debugging the windows service by attaching to the running process and see what it generates. If your service consumer is a web app, look at F12 developer tools and see what is getting sent back int he response stream.
Related
I am trying to change the format of ToLongDateString to be in my local culture (da-DK).
For now I am doing the following, and if it can be done in a better way, then it will be very appreciated:
CultureInfo cCulture = new CultureInfo("da-DK");
string dateTimeStr = freeSeat.FreeDate.ToLongDateString().ToString(cCulture);
This works as expected on my local development environment, but when I deploy it to AWS lambda, I just get the English culture format. I am pretty sure the issue is that in AWS the C# core code is running on Linux.
I hope someone can give me some input how to solve this.
The ToLongDateString method returns a string formatted according to the current thread culture. Calling ToString method later is useless.
Do it like this:
CultureInfo cCulture = new CultureInfo("da-DK");
string format = cCulture.DateTimeFormat.LongDatePattern;
string dateTimeStr = freeSeat.FreeDate.ToString(format, cCulture);
When my application starts, it sets its own culture to CultureInfo.InvariantCulture but in some places, I want to use localized number formatting according to what the user has set in Windows. How can I do this?
System.Globalization.CultureInfo.CurrentCulture only returns the thread's culture which is no longer the user's default.
I'm hoping for a more elegant way than storing the thread's default culture before changing it or creating a new thread just to read the culture out of it.
Maybe there's a built-in .Net wrapper for the Windows function GetUserDefaultLocaleName?
System.Globalization.CultureInfo has an internal property named UserDefaultCulture which is the equivalence of the Win32 GetUserDefaultLCID() as commented in .NET Source code:
//
// This is the equivalence of the Win32 GetUserDefaultLCID()
//
internal static CultureInfo UserDefaultCulture
So you can use it to get user default culture this way:
var property = typeof(System.Globalization.CultureInfo).GetProperty("UserDefaultCulture",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
var culture = (System.Globalization.CultureInfo)property.GetValue(null);
Also as another option, you can create a new thread and use its CurrentCulture property:
var culture = new System.Threading.Thread(() => { }).CurrentCulture;
I have the following snippet of Code for Convert Gregorian Date to Hijri Date.
public static string GregoriantoHijri(DateTime gregorianDate)
{
CultureInfo arCI = new CultureInfo("ar-SA");
var hijriCalendar = new HijriCalendar();
hijriCalendar.HijriAdjustment = App_Code.StoreRetrieveSettingsAssist.getHA();
arCI.DateTimeFormat.Calendar = hijriCalendar; //CODE FAILS HERE
string hijriDate = gregorianDate.ToString("dd-MM-yyyy", arCI);
return hijriDate;
}
This code runs perfectly for my Windows Mobile App which is also posted on Store.
However the same code is giving me issues in Xamarin.Android
The Error:
System.ArgumentOutOfRangeException:
Not a valid calendar for the given culture.
Parameter name: value
I don't understand why codes using same .NET base class have issues on different platforms. Can you suggest a workaround cause this doesn't seem to work.
You might want to consider NodaTime. It is supposedly more robust than the native .NET datetime handling, and is supposed to support Hijri.
I have screen in c# asp.net webapplication, where i add news on particular dates.And can edit those dates also.It workes in my local sytem.But shows datetime error when it was running in iis 7 server(Used sql database).And i knew that the short date and long date format in server was different from local system.So i changed date format in local system same as in iis.But still it is working properly.
Instead of guessing culture settings write code that sets one you need before reading from database/restore after unsing Thread.CurrentCulture property. Simialr to code below (need to also use CurrentUICulture, chose cuture you need and wrap code around setting/restoring into try/finally for real code)
var oldCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
// read from DB
...
Thread.CurrentThread.CurrentCulture = oldCulture;
I'm trying this in two application; a console application and a web application.
In the console app when I try Double.Parse("0.5") it gives 0.5 or Double.Parse(".5") gives 0.5
But in the web application Double.Parse("0.5") gives 5.0 and Double.Parse(".5") gives exception
Input string was not in a correct format.
Can any one tell how can resolve the issue in web app?
You should provide culture information otherwise it uses the culture info from the currently running thread. Try this instead:
CultureInfo cultureInfo = CultureInfo.InvariantCulture; // or whatever you prefer
double result = double.Parse(".5", cultureInfo);