Quirk in the DateTime class

by Mads Kristensen 5. January 2008 23:01

I experienced a strange behaviour with the DateTime class and formatting today. For some reason this error only occurs when you format a DateTime in certain cultures like Italian. The error is not present in English, Danish and most other cultures.

It happens when you use the DateTime.ToString and DateTime.ParseExact methods. When you write the following:

String date = DateTime.Now.ToString("yyyy-MM-dd HH:mm")

You would expect the date variable to be formatted like so 2008-01-05 11:30. In Italian it doesn’t. Instead it replaces the colon with a period which produces this 2008-01-05 11.30. This might be correctly formatted for the Italian culture, but I explicitly wrote I wanted the colon delimiter in the format string. However, there is a workaround.

All you need is to change the format string into a less obvious one. The following produces the right colon delimited date and time string:

String date = DateTime.Now.ToString("yyyy-MM-dd HH\\:mm")

Strangely enough, you have to escape the colon with two backslashes for it to work. This trick seems to work in all cultures.

* Only $4.95/month ASP.NET & Windows 2008 + IIS 7 Hosting! FREE SQL Included

Tags: ,

Server-side

Comments

1/6/2008 5:49:20 AM #

Jakob Andersen

The escaping isn't so strange the first slash is to escape the second \ from the C# compilers string handling so this would also work:

string date = DateTime.Now.ToString(@"yyyy-MM-dd HH\:mm")

The reason for ":" needed to be escaped is that it is the way you specify a timeseparator in a DateTime format string, the same goes for "/" which is the date seperator in a formatstring. The time and dateseparators can be found on CultureInfo.DateTimeFormat.TimeSeperator and CultureInfo.DateTimeFormat.DateSeperator and they are different that ":" and "/" for many cultures which easily can be determined by looping over the specific cultures using the following code:

foreach(CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures)){
        if(ci.DateTimeFormat.TimeSeparator != ":"){
          Console.WriteLine("Time: " + ci.Name + " " + ci.DateTimeFormat.TimeSeparator);
        }
        if(ci.DateTimeFormat.DateSeparator != ":"){
          Console.WriteLine("Date: " + ci.Name + " " + ci.DateTimeFormat.DateSeparator);
        }
      }

Jakob Andersen Denmark |

1/6/2008 6:41:04 AM #

Mads Kristensen

It is not correct that it will work with a single backslash. That's what makes it strange. It needs an escaped backslash.

Mads Kristensen Denmark |

1/6/2008 7:43:45 AM #

Mads Kristensen

...also, I know that there are different delimiters for different cultures as you write, but the problem is that I requested a specific formatting and the DateTime class didn't deliver it. This should have nothing nothing to do with how cultures format date and time, since I explicitly requested a colon.

Mads Kristensen Denmark |

1/6/2008 8:24:27 AM #

ck

If you read the documentation:
msdn2.microsoft.com/en-us/library/w2sa9yss.aspx

You see that the culture's settings are taken into account, which is why it removed the : for you.  Where as the strait tostring does not.

So it was doing what it was supposed to do.

The other issue (the need for a double escape) is just poor programming on somebody's part at Redmond.

ck United States |

1/6/2008 3:32:37 PM #

Tommy Carlier

If you want culture-independent formatting, you could use the invariant culture, like this:
string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);

Tommy Carlier Belgium |

1/6/2008 7:48:12 PM #

Jakob Andersen

Escaping with the single slash would work if you Add @ before the string as i wrote, the first escaping is for C# to understand that you have a backslash in you string.

Jakob Andersen Denmark |

1/6/2008 7:50:47 PM #

Mads Kristensen

@Jakob
I know, but it still doesn't change the fact that the DateTime class didn't return the format I provided.

Mads Kristensen Denmark |

1/6/2008 7:56:27 PM #

Jakob Andersen

The problem is you used ":" which is special in datatime format string, the same is "/" so i would argue it returned correctly. What you want is to format it using no culture specific settings and that is done using Tommy's suggestion.

Jakob Andersen Denmark |

1/6/2008 9:08:08 PM #

Cristiano

I have linked the post near the Italian forum of BlogEngine.Net:
www.italianbloggers.it/forum/viewforum.php?f=19

Thanks a lot to all Wink

Cristiano Italy |

1/8/2008 10:47:27 PM #

Nicolas Cadilhac

as other specified, this is not an error at all that your ':' character has been replaced. This is the way it is supposed to work. The ':' character is parsed and understood as "the time separator for the current culture" the same way as 'd' is understood as the day of the month. If you want explicitely a particular character you can put it inside single quotes, so your format string would be yyyy-MM-dd HH':'mm.

Nicolas Cadilhac Canada |

1/18/2008 3:26:59 PM #

Krzysztof Koźmic

If you don't specify which culture should be used, the CultureInfo.CurrentCulture will be used to display the string, and basically, what Nicolas said happends. If you want to make sure that ALWAYS string will look the same you should use Tommy Carlier's solution: it's the most right and the most elegant. Your character escaping is more of a hack ;)

Krzysztof Koźmic Poland |

1/18/2008 6:11:50 PM #

Krzysztof Koźmic

You may be interested in blog post I wrote regarding this issue: kozmic.pl/.../...-datetime.tostring-explained.aspx

Krzysztof Koźmic Poland |

1/19/2008 9:58:35 AM #

Lucas

the colon is considered a special code, same with "d", "m", etc. for example, if you wanted an actual "d" in the string output, you would have to escape them as "\d" (plus any escaping needed for the backslashes)

"yyyy-M-d" => "2008-1-18"
"yyyy-\M-\d" => "2008-M-d"

the colon is replaced with the culture's time separator the same way 'M' and 'd' are replaced.

Lucas Puerto Rico |

Comments are closed

About the slave

Mads Kristensen Mads Kristensen
Web developer at ZYB and founder of BlogEngine.NET. More...

LinkedIn ZYB Facebook Last.fm Twitter View Mads Kristensen's profile on Technorati

The Lounge

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008