Short Date Formats Don’t Always Fit Neat Patterns


I’m often asked something like “What’s the date separator  for locale XXX?”  Well, not every locale fits our preconceived MM/dd/yyyy concepts.  Some of the built-in values that developers may not expect:

  • dd/MM yyyy — 20/10 2010 — This one has different separators (space and /) so you tell me which one DateTimeFormatInfo.DateSeparator is supposed to use?
  • d. M. yyyy — 20. 10. 2010 — This one has 2 character separators (period space)
  • dd-MM-yy — 20-10-13 — This one has a non-Gregorian calendar, also some locales have 2 digit years in Gregorian.
  • d.M.yyyy. — 20.10.2010. — This has a trailing period
  • d.M.yyyy r. — 20.10.2010 r. — This one has an r. after the date.

And since there are user overrides and custom locales, this just scratches the surface.  (Don’t ignore user overrides!) Some obvious ones:

  • dd MMM yyyy — 20 Oct 2010
  • dd of MMM yyyy — 20 of Oct 2010

So the moral is to use the short (or long) date formats provided by the system and don’t try to build your own.  That’s a bit tricky in some places, like Calendar titles, or controls to filter dates, but it’s important to respect the user settings and not make assumptions about their date (or time) formats.

Short time formats have similar issues.  (eg: “12h 42m 15s”, or “12:42 uhr”, or….).  Long dates are even more varied, with prepositions in the format, or even different word forms for the month names, etc.

Good practices:

  • Use the user settings for the date/time formats
  • Use date pickers instead of entry forms when possible (parsing user input reliably is nearly impossible, which is why you end up with individual entry fields for day, month & year, with explicit instructions).
  • Never rely on date or time separators, it’s not as simple as “which one, :, -, ., or /?”
Comments (5)

  1. Bob says:

    I wonder if anyone has written an algorithm that will try to parse all these custom date strings into a DateTime object (when DateTime.TryParse() fails)?  I realize it would be impossible to hit them all, but it would be possible it get a good chunk of them I think.

  2. shawnste says:

    Well, there's a reason why Parse isn't perfect:)  ParseExact() works when you know the exact format, but Parse has to make some guesses and assumptions.  If you knew a lot more about your inputs, then you might be able to do some better guesses, but Parse is sort of general.

    The difficulty of parsing is why I strongly encourage using a date picker type control for input.  Or if it must be keyed in (like entering 100 dates), then requiring an explicit format so the user knows what to type.  For machine-generated data intended to be machine-read, then a fixed format is essential.

  3. shawnste says:

    Well, there's a reason why Parse isn't perfect:)  ParseExact() works when you know the exact format, but Parse has to make some guesses and assumptions.  If you knew a lot more about your inputs, then you might be able to do some better guesses, but Parse is sort of general.

    The difficulty of parsing is why I strongly encourage using a date picker type control for input.  Or if it must be keyed in (like entering 100 dates), then requiring an explicit format so the user knows what to type.  For machine-generated data intended to be machine-read, then a fixed format is essential.

  4. It's easy says:

    '/' separator is used in US. E.g. 01/02/2003 (Jan 1, 2003)

    '-' separator is recommended by ISO 8601. E.g. 2001-02-03 (Feb 03, 2001)

    '.' separator is used in some European counties. E.g. 01.02.2003 (Feb 1, 2003)

    This simple rule allows to distinguish what user meant when they typed e.g.:

    01/02/03 or 01-02-03 or 01.02.03.

    Even  working in the US ,I prefer ISO way, because it allows to keep e.g. file / folder names organized (sorted) alphabetically and by date at the same time…

  5. shawnste says:

    That might work sometimes, but some places use space, eg: 01 02 2003, and space, . and – are also used in the US sometimes.  And (a few) locales have mixed up – and / or space, like 01/02 2003.  So there isn't really "a separator", nor 100% consistent rules about their use

    FWIW: ISO is sort of othogonal to globalization.  If you have a "standard", then you shouldn't be using locale specific rules, you should be using the standard's rules, which are simple to hard code and avoid asking CultureInfo or GetLocaleInfo for the data.