Question

I have a datetime field which has the following format ...

dd/mm/yyyy - this is the UK/GB/AU format

Sometime the dates come across though in US format ...

mm/dd/yyyy

This works fine if the DAY is beyond 12 and the MONTH is within 12.

If not, then the date is automatically assumed to be in US format.

ie: 01/03/2014 could be interprited in both ways - UK and US (1st of March or 3rd of January)

How can I parse this in C# to know which culture it is? Obviously there is no direct single-line way of doing this because parsing such dates in either US or UK culture will return the same date back again.

The question is, regardless of what values we have in DD and MM, how can I force US dates to be UK format and leave UK formatted dates alone?

I am trying to do this using the following code ...

//get the date from a control
TextBox tbDate = (TextBox)e.Row.FindControl("tbInvoiceDate");
if (tbDate != null && tbDate.Text != "")
{
   //define the two cultures I want to test
   IFormatProvider cultureAU = new CultureInfo("en-AU", true);
   IFormatProvider cultureUS = new CultureInfo("en-US", true);

   //try and parse the date into US culture
   DateTime dtINV;
   DateTime.TryParse(tbDate.Text, cultureUS, DateTimeStyles.None, out dtINV);

   //"force" the date to be in UK format
   String strDate = (dtINV != null && tbDate.Text != "") ? dtINV.ToString("dd-MM-yyyy") : "";

   //return the new format back to the textbox
   tbDate.Text = dtINV.ToShortDateString();               
}

The above code does not work because US dates are left as US dates because the day and the month, as I explained above are also in the correct "format" for being a UK date.

I think I am missing some extra code here to test the day and month separately and then format the date.

Thanks in advance.

[UPDATE]

I've resolved it somewhat (see further down), by using the following code, and assuming the date in the textbox is always in mm-dd-yyyy format.

TextBox tbDate = (TextBox)e.Row.FindControl("tbInvoiceDate");
if (tbDate != null && tbDate.Text != "")
{
   IFormatProvider cultureAU = new CultureInfo("en-AU", true);
   DateTime dtIn;
   DateTime.TryParse(tbDate.Text, cultureAU, DateTimeStyles.AssumeLocal, out dtIn);
   DateTime dtInv = new DateTime(dtIn.Year, dtIn.Day, dtIn.Month);
   tbDate.Text = dtInv.ToShortDateString();               
}

The problem now is that when I over type a new date in AU format, the system kicks in before the code above, with the following error ...

the conversion of char data type to smalldatetime data type resulted in an out-of-range smalldatetime value the statement has been terminated

So it seems something out there is now expecting the field to be in US format. But I tried typing in US format say 31-01-2014 and it still gives the above error, so not sure where to go now.

Thanks everyone thus far.

Was it helpful?

Solution

how can I force US dates to be UK format and leave UK formatted dates alone?

There is no automatic way to know this. If you receive a date of "04/03/2014", there is no way without extra information to know whether that represents March 4th or April 3rd.

In order to properly handle dates, you need to provide the culture along with the date, always use a specific culture, or keep the date represented in a DateTime instead of a string.

OTHER TIPS

In a nutshell, you can't. As noted, something like 01-02-2014 is ambiguous. Lacking context, only the author knows whether 1 February 2014 or 2 January 2014 was intended.

If your data is coming from a web or other app, you could

  • use a date picker so that you control the format of the data
  • ask the user to provide locale information along with the data.
  • get the locale information from the client machine.

And if the data carries location information associated with the date(s) in question (e.g., postal address or postal code, etc.), you could use that additional data to make some [presumably] reasonable assumptions about what forms the date might take.

If you are storing it in SQL Server, the value should be stored as a datetime data type.

If you are going to store it as text (string), there is an ISO Standard (ISO 8601:2004)for non-ambiguous text representations of date and time values that collate and compare in the manner you'd expect. For more, visit

xkcd on ISO 8601

DateTime is a struct, so comparing it to null is not a good idea. dtINV != null is always true.

You should use DateTime.TryParse return value, which indicates if parsing was performed correctly:

if(!DateTime.TryParse(tbDate.Text, cultureUS, DateTimeStyles.None, out dtINV))
{
    //"force" the date to be in UK format
    String strDate = (dtINV != null && tbDate.Text != "") ? dtINV.ToString("dd-MM-yyyy") : "";
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top