DateTime.Parse() works on one machine but not the other - c#

I'm using the Parse method to convert a string to a DateTime object:
requestRecord.TerminationDate = DateTime.Parse(reader.ReadString("Termination_Date"));
This code works on one machine but throws an exception on the other. I think the issue may perhaps be to do with the local culture. Looking at the taskbars on the two machines the one that throws the exception has the date as 01/12/2014 whereas the other shows 12/01/2014.
Is there some way that I can rewrite the above code so that it works on both machines regardless of the local DateTime culture?

I guess the culture settings differ on both machines. Try to supply the format. That explains why the date format is interpreted differently on both machines:
requestRecord.TerminationDate = DateTime.ParseExact
( reader.ReadString("Termination_Date")
, "dd/MM/yyyy"
, CultureInfo.InvariantCulture
);
In this way, you are not depending on the machine and it's settings, but on the format you know.
Depending on what reader is, you might want to use reader.GetDateTime, which does all this for you already, for example SqlDataReader.GetDateTime.

Related

DateTime.Parse sometimes throws FormatException over Pipes

I am trying to send a DateTime from one process to another. My first thought was to send the DateTime as a string and parse the string back to DateTime onces received. Unfortunately on some machines I get a FormatException even though the string looks good e.g. "31.10.2019 12:00:00" (no hidden characters).
The code looks like this, I will omit the communication since the string is correctly transferred.
var datetimeAsString = SomeDateTime.ToString(); // "31.10.2019 12:00:00"
Pipe.Send(StringToBytes(datetimeAsString));
// Data gets send
var datetimeAsString = BytesToString(receivedBytes); // "31.10.2019 12:00:00"
var datetime = DateTime.Parse(datetimeAsString);
Please note that it works on some machines.
TL;DR
When trying to send DateTime between different systems, do NOT convert it to a string using ToString() without parameter use DateTime.ToBinary and DateTime.FromBinary instead OR if you want a string specify a culture e.g.
var datetimeAsString = thisDate.ToString(new CultureInfo("en-us"));
DateTime.Parse(datetimeAsString, new CultureInfo("en-us"));
PS: I think this not only applies to situations where you want to exchange data but also to other situations and therefore should be seen as a general advice.
--
The problem was that the software that sent the DateTime converted the DateTime.ToString() to a German format, even though the software was in English. The receiving software was sometimes in German and sometime in English. The software with the German language was able to use DateTime.Parse on the German string, the other systems weren't.
The solution was to not convert the DateTime to a string but to a long using the DateTime.ToBinary method. I think is would also been possible to solve it with CultureInfo.InvariantCulture, but we thought long was much cleaner.

Converting DateTime.Now from "ar-EG" to "en-US" to avoid ص/م time abbreviation

I want to convert DateTime.Now object from culture("ar-EG") to culture("en-us") to get rid of [ص/م] time abbreviations so I used this piece of code string cnow = DateTime.Now.ToString(new CultureInfo("en-US")); it works fine., but when trying to convert it back to DateTime object using this code DateTime dt = DateTime.Parse(cnow) I get this exception
String was not recognized as a valid DateTime
I can not figure it out why this happen. and how to get this conversion done in this case?
-- Update --
I have to do this conversion as I'm trying to get TimeSpan between two different dates with two distinct culture as mentioned above.
-- Update 2 --
The necessity of this conversion is because my application will run on many different cultures and results errors when inserting these dates into database.
Use the DateTime.Parse overload that also takes an IFormatProvider (CultureInfo implements IFormatProvider). Otherwise, the current culture will be used for parsing.
You can use this i hope help you to solve problem : https://msdn.microsoft.com/en-us/library/5hh873ya(v=vs.90).aspx
I found the clue, just I will force my entire application to work on a specific culture instead of relying on Windows current culture using this line of code at very start of application code:
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

DateTime.TryParse issue, may relate to Globalization Setting in IIS

Basically,I am reading excel file where one of that columns has date format like : dd/MM/yyyy eg: 11/04/2016
When I am using DateTime.TryParse() to parse that string into datetime method TryParse() treated first numbers like month (number 11 in example above). However the same code running on the other computers will take the second number (04 in example above) as the month.
So my question is why there is a difference between them, what actually decide the behavior of TryParse method?
I think the main difference is in IFormatProvider (hard to say if I can't check some settings in target system), but I usually use other method to get proper DateTime object:
DateTime someDate = DateTime.ParseExact(myStringDate, "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture);
It always gives me what I want no matter how client environment is configured.
Hope this helps. :)
From DateTime.TryParse(String, DateTime) documentation:
Because the DateTime.TryParse(String, DateTime) method tries to parse
the string representation of a date and time using the formatting
rules of the current culture, trying to parse a particular string
across different cultures can either fail or return different results.
If a specific date and time format will be parsed across different
locales, use the
DateTime.TryParse(String, IFormatProvider, DateTimeStyles, DateTime)
method or one of the overloads of the TryParseExact method and provide
a format specifier.
That means your computers have different culture settings which is pointed in CurrentCulture property.
Looks like one computer's current culture have dd/MM/yyyy and the other computer's current culture have MM/dd/yyyy as a standard date and time format.
Since you are sure your values are always in dd/MM/yyyy format, I would use DateTime.ParseExact instead of Datetime.TryParse or DateTime.TryParseExact methods like;
var dt = DateTime.ParseExact(yourColumnValue, "dd/MM/yyyy", CultureInfo.InvariantCulture);
Or you can sets all computers current culture to like the first computer but remember, CultureInfo data is not a stable data that might be change in future with a windows update, .NET Framework version or OS version.

Why date is displayed differently at server and locally?

I am reading data from an API file, which has this format
<DataPoint>
<Amount>38.361</Amount>
<Time>2014-01-02T12:00:00</Time>
</DataPoint>
when I get the time, and print it at my website at visual studio I get 02/01/2014.
However, If I upload it, I get 1/2/2014.
Why the same code produces different results when I use it at my pc, and when I upload it at the server?
And how I can fix that?
ps: I am programming in C# and I am using the object JArray to get the data if this is important
JArray a = JArray.Parse(text);
But it
That's because of the DateTime CULTURE info. British dates are arranged as dd/MM/yyyy and American dates are MM/dd/yyyy You could just use Datetime.ToString("dd/MM/yyyy") to convert it to datetime format you want to display.
Format in which numeric and datetime values are transformed into string depends on OS culture settings, when you don't set them explicitly in code. Looks like that's the case here.
If you need the same date/numeric format everywhere, no matter how user set's the OS preferences, you should provide IFormatProvider instance which will provide the formatting and override OS default one.
The most commonly used is CultureInfo.InvariantCulture:
var dateString = myDate.ToString(CultureInfo.InvariantCulture);

DateTime issue when global culture of the server is different on different servers

My website is hosted on multiple servers at different locations
Everywhere the Culture of the data format is different- we use mm/dd/yyyy format every where but incase some server has the culture set to dd/mm/yyyy then our website generates Datetime exception.
You should be specifying what culture you want to use whenever you convert a string to a date.
The culture you should be using depends on what culture the dates are formatted as. For example, if all dates you are parsing are formatted as Slovak:
String s = "24. 10. 2011";
Then you need to parse the string as though it were in Slovak (Slovakia) (sk-SK) culture:
//Bad:
d = DateTime.Parse(s);
//Good:
d = DateTime.Parse(s, CultureInfo.CreateSpecificCulture("sk-SK")); //Slovak (Slovakia)
If your dates are all in Tajik (Tajikistan Cyrillic), then you need to parse it as tg-Cryl-Tj:
String s = "24.10.11"
DateTime d = DateTime.Parse(s, CultureInfo.CreateSpecificCulture("tg-Cryl-Tj"));
Which leads to the question: what date format are you using? You should not be relying on the locale setting of the server, you should be deciding what format you want.
//Bad
String s = d.ToString();
//Good
String s = d.ToString(CultureInfo.CreateSpecificCulture("si-LK")); //Sinhala (Sri Lanka)
//s = "2011-10-24 12:00:00 පෙ.ව."
i suspect that you prefer to do everything in English. But then you have to decide which variant of English:
en-AU (English Austrailia): 24/10/2011
en-IA (English India): 24-10-2011
en-ZA (English South Africa): 2011/10/24
en-US (English United States): 10/24/2011
i suspect you prefer English (India) (en-IA).
But if you really can't decide what culture to use when converting dates to strings and vice-versa, and the dates are never meant to be shown to a user, then you can use the Invariant Culture:
String s = "10/24/2011" //invariant culture formatted date
d = DateTime.Parse(s, CultureInfo.InvariantCulture); //parse invariant culture date
s = d.ToString(CultureInfo.InvariantCulture); //convert to invariant culture string
Never, ever, store dates internally as strings. Not in the database, not in your app.
If you need to move date values between servers, go binary. Or if you really really have to use strings, use ToString(CultureInfo.InvariantCulture) - or simply serialize the Ticks property.
Also, never pass dates as strings to the database using SQL commands that you build using code. Use SqlParameter for that, or even better, rely on some O/R Mapper, such as Entity Framework or Linq to SQL.
If deployed to a server that's not under your control it's vitally important to make sure your code doesn't have hard-coded dependencies on the culture.
You'll most likely want to search your code for DateTime.Parse or similar. We have a set of extension methods on DateTime that we use instead to force the correct culture.
Never rely on the server's default locale. For your case, this means:
Use prepared statements where you pass the date as (unformatted) date object and not as (formatted) string object. You should never use strings to represent dates in your application anyway, as you cannot perform date-specific functions on them (like adding 1 month, getting the last day of the current week, etc.)
Use SQL functions like to_date and to_char everywhere (exact names depend on your DBMS), if you really need to use string objects in your application

Categories

Resources