My computer is configured with a culture that is not en-US
.
When using the native Win32 GetDateFormat
function, i get correctly formatted dates:
- 22//11//2011 4::42::53 P̰̃M]
This is correct; and is also how Windows renders it:
the taskbar
Region and Language settings
Windows Explorer
Outlook
When i try to convert a date to a string in .NET using my current locale, e.g.:
DateTime.Now.ToString();
DateTime.Now.ToString(CultureInfo.CurrentCulture);
i get an incorrect date:
- 22////11////2011 4::::42::::53 P̰̃M]
This bug in .NET is evident anyplace in Windows that uses the buggy .NET code:
Windows Event Viewer:
Task Scheduler:
SQL Server Management Studio:
How do i make .NET not buggy?
How do i convert dates and times to strings using the current culture (correctly)?
Note: The user is allowed to set their Windows to any locale preferences they want. As it is now, my program will not handle valid settings properly. Telling the user, "Don't do that" is pretty mean-spirited.
A similar example comes from Delphi, which assumes that a date separator can never be more than one character. When Windows is configured with a locale that uses multiple characters for the date separator, e.g.:
- sk-SK (Slovak - Slovakia) :
.
where dates should be formatted as:
22. 11. 2011
the code library fails to accept a date separator longer than one character, and falls back to:
22/11/2011
In the past some might suggest that you not to bother with such edge cases. Such suggestions carry no weight with me.
i'll avoid getting into a pissing match with someone who wants to alter the meaning of my question by changing the title. But the question is not limited to pseudo-locales, specifically designed to find bugs in applications.
Bonus Chatter
Here's a unique list of date formats from around the world:
- 11.11.25
- 11.25.2011
- 11/25/2011
- 2011.11.25
- 2011.11.25.
- 2011/11/25
- 2011-11-25
- 2011
- 25.11.11
- 25.11.2011
- 25.11.2011 г.
- 25.11.2011.
- 25//11//2011
- 25/11 2011
- 25/11/2011
- 25/11/2554
- 25-11-11
- 25-11-2011
- 29/12/32
Of particular interest is the last example which doesn't use the gregorian calendar:
- Arabic (Saudi Arabia)
ar-SA
: 29/12/32 02:03:07 م - Divehi (Maldives)
dv-MV
: 29/12/32 14:03:07 - Dari/Pashto (Afghanistan)
prf-AF / ps-AF
: 29/12/32 2:03:07 غ.و
Although those are edge cases that you'd never have to worry about.
Update 14//12//2011:
Another demonstration of the bug is that Datetime.Parse
cannot parse DateTime.ToString
:
String s = DateTime.Today.ToString("d"); //returns "14////12////2011"
DateTime d = DateTime.Parse(s); //expects "dd//MM//yyyy"
The .Parse
throws an exception.
Update 02//8, 2012 09::56'12:
Any use of a date separator is depricated, in addition to being incorrect. From MSDN:
LOCALE_SDATE
Windows Vista and later: This constant is deprecated. Use
LOCALE_SSHORTDATE
instead. A custom locale might not have a single, uniform separator character. For example, a format such as "12/31, 2006" is valid.LOCALE_STIME
Windows Vista and later: This constant is deprecated. Use
LOCALE_STIMEFORMAT
instead. A custom locale might not have a single, uniform separator character. For example, a format such as "03:56'23" is valid.
This specific bug is due to the transformation of some special characters that aren't escaped in the patterns like
ShortDatePattern
./
in a pattern means "insert the date separator" but here the expansion is already done (at least on my system) when the string is copied from the system to theDateTimeFormat
structure. Sadly it is missing an escaping (Obviously not visible on any language not using a special character as a separator and not visible in english as it is replaced with itself)The only solution seem to be to escape the separators in all the patterns of the
DateTimeFormat
instance :Here's full code samples for all three common cases
Date to string
Time to string
Datetime to string