2

I need to compare two DateTime values in my DotNetNuke module, like this:

// This value actually comes from the database.
DateTime time1 = Convert.ToDateTime("6/2/2013 5:21:05 PM");

// Say it is now "5/31/2013 2:20:33 AM"
DateTime now = DateTime.Now;

int num = DateTime.Compare(time1, now);

As you can see, num == 1 because the DateTime value of time1 is greater than the DateTime value of now. But when I change the language to German (de-DE) in the DotNetNuke settings, the value of now becomes - 31/5/2013 2:20:33 AM. The result is that num becomes -1, meaning time1 is earlier than now. This is incorrect because time1 is actually later than now.

The time1 value is always in mm/dd/yyyy format because it is coming from the server.

So, how do I get the right comparison in case another language is set in DotNetNuke? When I searched the web, I found that I can correct the time with the following code:

provider = new CultureInfo("en-US");
DateTime.ParseExact("5/31/2013", "d", provider);

Is that correct? Is there a better way to handle this concern?

Edited

forgot to say that time 1 comes from my website server before saving to db and is compared with client's website's datetime value in now variable.all codes is my app which is in that client site.these codes at first accessed time1 date by .net methods of getting remote site data.so when that dnn site language is set as de-DE look 'now' variable value is day first which is reverse from my site date is US format month first.in consequence when comparison takes place, my server date is resulted as earlier than client site date! And everything breaks.FYI my server date came as a i week later date which is 2nd june for license purpose.

Edited again:

Hi every1.I found a solution by the following codes.This date comes from my another server as i said above - "6/15/2013"(changing it was bef4 6/2/2013).It's in string format, why it's a string? it's a long history.just let it be a string right now.before converting to string it was in US date format(month before).Now in current website where my app is, these codes seem working.Hope i am not wrong, please confirm

CultureInfo provider = CultureInfo.InvariantCulture;
provider = new CultureInfo("en-US");
DateTime time1 = DateTime.ParseExact("6/15/2013", "d", provider);                    
DateTime now = DateTime.Now;
int num = DateTime.Compare(time1, now);

"num" returning 1 which is right whether dnn site language is German or English.

dev-m
  • 440
  • 8
  • 24
  • Your solution thats you found Is correct [Link](http://msdn.microsoft.com/es-es/library/9xk1h71t.aspx) If you made a convert is necessary the culture info. I think is a good way but I dont know whether It's the good practice. – Wilfredo P May 30 '13 at 23:19
  • I see you are relatively new to StackOverflow. Welcome! But please try to do better in the future with asking your questions using proper formatting and language. Also, this particular question has been asked *many* times before, just in slightly different ways. See [here](http://stackoverflow.com/q/15474497), [here](http://stackoverflow.com/q/9235946) and several others (too many to list). But since I couldn't find an *exact* duplicate, I will also answer below. – Matt Johnson-Pint May 30 '13 at 23:28

1 Answers1

2

As you pointed out, there are cultural differences to how we treat dates when they are represented by strings. The DD/MM/YYYY format is common throughout much of Europe and other parts of the world, while MM/DD/YYYY is used almost exclusively by the USA (with a few exceptions). There are plenty of other formats as well.

There is one important format that you should know, which is the ISO8601 standard. You may typically see this as a timestamp, such as 2013-05-31T02:20:33. Sometimes a trailing Z is included to indicate that the time is at UTC. You might also see an offset such as -07:00 or just -0700. This is all part of the same standard. The most common usage is also denoted in RFC3339. Whenever you actually need to send a DateTime as a string, you should probably be using this format. (The exception is when showing the string to a user, and when gathering input from a user.)

Now, you should understand that a DateTime is not a string value. It is internally represented by a 64-bit integer. It does not internally keep any format or culture settings. Conversion between DateTime and string should only be done for purposes of input and output. Usually this is in your user interface, or in the case of ASP.Net, it can be on your web page.

Anywhere else that you work with DateTime, you should not be dealing with strings at all. Especially when comparing values. Let us dissect your code. First we had this line:

DateTime time1 = Convert.ToDateTime("6/2/2013 5:21:05 PM");

Now you said it was coming out of the database, but if that is the case then you shouldn't have a string. Let's assume you are using a SQL Server database (but the same concept applies in others), and the data is in a column of DateTime type. When you retrieve the value from your data access layer, it should flow from SQL to .Net as a pure DateTime. There is no string involved. Let's just assume you are using ADO.Net and you have a DataReader. You should be loading your value as:

DateTime time1 = (DateTime)reader["columnname"];  // good

If instead you are doing something like this:

DateTime time1 = Convert.ToDateTime(reader["columnname"].ToString());  // bad!

then you are introducing culture info into the string that you are using as the intermediate step. This is likely the source of your problem. Don't use a string when you don't need to.

Also, I would avoid using Convert.ToDateTime at all. If you really do need to parse a string, you should use DateTime.Parse, and if you already know the exact format of that string then you should use DateTime.ParseExact.

Next line from your code was:

DateTime now = DateTime.Now;

For this, you should understand that you are taking the local time from the clock on your server. This is probably not the time of the user of your site. And since you are comparing it to a database value, that means you are storing local times in your database as well. This can be very problematic, because the server could have particular time zone settings. Also, if the time zone goes through changes for Daylight Saving Time (a.k.a. Summer Time), then there are some values that don't exist and some values that exist twice. This can cause major issues, especially when comparing these values. The better approach would be to use either DateTime.UtcNow, or use the DateTimeOffset type instead of the DateTime type. You can read more about this, here.

Last line:

int num = DateTime.Compare(time1, now);

This is fine, but you might find it easier to use regular boolean comparisons, such as:

if (time1 >= now) ...

So how then to deal with culture issues? When parsing input from the user, do something like this:

// Use the culture setting of your user.  Perhaps DNN has this already.
CultureInfo provider = new CultureInfo("de-DE");

// Parse the input string, but let the provider do the work to know the format.
DateTime dt = DateTime.Parse("31/5/2013", provider);

// Send data back to the user with the same provider.
string s = dt.ToString("d", provider);

You may prefer to use the TryParse method, in case your user gives bad data:

DateTime dt;
if (!DateTime.TryParse(s, provider, DateTimeStyles.None, out dt)
{
    // handle invalid data
}

Lastly, you should familiarize yourself with DateTime.Kind, and understand the difference between Local, Utc, and Unspecified kinds. And if you find you need to deal with other time zones in your application, then you may also need to learn about the TimeZoneInfo class.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • hi my problem not solved yet!.As u see in this example i used "5/31/2013" as a sample.actually in parseexact method i want to convert datetime.now value to US date format(month at first) then i can compare time1 date with date in now variable whether current site url is de-DE or en-US.As you see when language is de-DE it reurns wrong value "-1".Plz help anyone asap – dev-m May 31 '13 at 15:26
  • No, you have it backwards. Leave `DateTime.Now` as a `DateTime`. If `time1` is also a `DateTime`, then you have no formatting or language concerns. You need to be more concerned with how you got `time1` into a `DateTime` to begin with. – Matt Johnson-Pint May 31 '13 at 15:30
  • Yes as you see in code time1 comes from my server as i said editing the Q.first that date i convert to datetime and save in time1.so reading my problem, can anyone give me working codes by which comparison results that time1 is higher than date in now whether site lang is set german or english? – dev-m May 31 '13 at 16:37
  • Please, stop and try to understand what I am telling you. The only thing that is impacted by the site language is how `DateTime` values are parsed *from strings*. If you never deal with strings, then you don't have this problem. You say you have the problem, so you must be getting `time1` from a string somewhere, and you should not do that! – Matt Johnson-Pint May 31 '13 at 16:41
  • Update your question again, and show the code where `time1` actually originates from - rather than the made up sample. – Matt Johnson-Pint May 31 '13 at 16:44
  • Its come from another server which is mine.and its true that i had to save that so its saved as string and i convert that string back into time1 as datetime to make comparison.believe me there is no more code needed to write here as i have expressed well in q. – dev-m May 31 '13 at 16:59
  • Ok, I give up. The problem is in the code you don't want to show. If you go from `DateTime` to `string` and back to `DateTime`, then you have introduced culture issues like the one you are describing. My answer remains the same - *don't do that*. If you are saying, "sorry I'm going to do it anyway", then my answer is "well then you will have to live with the consequences". – Matt Johnson-Pint May 31 '13 at 17:27
  • well why not this anyone pointed me out that as my time1 datetime is always US format(comes from my server) so if i re-arrange date in now variable like arranging month/day/yyyy format then comparison goes right.simple! ? or wrong? – dev-m May 31 '13 at 21:30
  • Wrong. A `DateTime` on your server (assuming a `datetime` field in SQL Server) is not a string. It's a `datetime`. You see it as a string if you query in SQL Management Studio, but its not a `varchar`, it's a `datetime`. It's stored internally as a single integer number, and passed as a single integer number, and *should* be loaded into a .Net `DateTime` as an integer number. See the part of my answer where I show getting the value out of an ADO.Net `DataReader`. – Matt Johnson-Pint May 31 '13 at 23:49
  • The syntax is different if you are using a `DataTable`, or if using Entity Framework, Linq-to-sql, NHibernate, etc., but the idea is the same. Don't use a string as an intermediary. – Matt Johnson-Pint May 31 '13 at 23:51
  • My previous commen t was not perfect.it seems i found a solution - my server date(6/2/2013 in us format) which i getting as string need to be parsed using parseexact method with provider =new cultureinfo(en-US).then comparison with date in now variable goes ok.i think i am right now? – dev-m Jun 01 '13 at 00:25
  • No. The code that is getting you a date in string format is also prone to culture settings when it does a ToString. Please, trust my vast experience with this, I am trying to save you much trouble later. For example, if you assume US format string coming out of your ToString, then if you ever deploy to a server with a different setting your code will break. Really, don't use a string between .Net and the database. Keep it a `DateTime`. – Matt Johnson-Pint Jun 01 '13 at 00:40
  • I edited answer to include my solution so that you getting it as there is no ToString or db to be counted. – dev-m Jun 01 '13 at 11:31