3

I had a quick function to format a date, here it is:

public static string archiveServerDateTime(string datetime)
    {
        DateTime tempDateTime = DateTime.ParseExact(datetime,"dd.MM.yyyy HH:mm:ss", null);
        return tempDateTime.ToString("yyyy/MM/dd:HH:mm:ss");
    }

only to find the output of the function = 2009.10.22:16:21:03, and amazingly this is only on 1 production server, test server worked perfectly fine......

So now I rewrote the function to old school style:

public static string archiveServerDateTime(string datetime)
    {
        DateTime tempDateTime = DateTime.ParseExact(datetime,"dd.MM.yyyy HH:mm:ss", null);
        string yearPart = Convert.ToString(tempDateTime.Year);
        string monthPart = Convert.ToString(tempDateTime.Month).PadLeft(2,'0');
        string dayPart = Convert.ToString(tempDateTime.Day ).PadLeft(2, '0');
        string hourPart = Convert.ToString(tempDateTime.Hour).PadLeft(2, '0');
        string minutePart = Convert.ToString(tempDateTime.Minute).PadLeft(2, '0'); 
        string secondPart = Convert.ToString(tempDateTime.Second).PadLeft(2,'0');

        return yearPart + @"/" + monthPart + @"/" + dayPart + ":" + hourPart + ":" + minutePart + ":" + secondPart; 
        //return tempDateTime.ToString("yyyy/MM/dd:HH:mm:ss");
    }

So I ask you ladies and gentlemen, was I replacing perfectly good code to begin with, or is this a Microsoft bug of some kind? Can we really trust these new language features that are seemingly not so rock solid, or am I just missing something?

EricSchaefer
  • 25,272
  • 21
  • 67
  • 103
JL.
  • 78,954
  • 126
  • 311
  • 459

2 Answers2

26

You should pass DateTimeFormatInfo.InvariantInfo as an argument to the DateTime.ToString method. / in the format string does not mean "/" character all the time. It resolves to the date separator of the current culture:

return tempDateTime.ToString("yyyy/MM/dd:HH:mm:ss", DateTimeFormatInfo.InvariantInfo);

In general, it's a good practice to always clearly specify the culture in ToString and Parse methods (not only on DateTimes). FxCop (VS Code Analysis) has rules that spit out warnings when you don't do this. It's critical for non-US cultures and the importance is often underestimated by many programmers.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 1
    doc link: http://msdn.microsoft.com/en-us/library/system.datetime.tostring(VS.71).aspx –  Oct 31 '09 at 22:46
  • Thanks Mehrdad, do you like my old school function above? – JL. Oct 31 '09 at 22:47
  • JL: I prefer your first function if done correctly. The old school way is harder to understand (the intention is not obvious) and is more prone to errors. – Mehrdad Afshari Oct 31 '09 at 22:49
  • I was 1/2 cocked, I needed to understand the function fully... Still don't but will invest the time to learn this. – JL. Oct 31 '09 at 22:54
  • 1
    JL: I recommend you fully study globalization stuff related to parsing and formatting strings. If you search SO, there are many instances of similar globalization problems even for numbers. (You might not expect `double.Parse("5.000")` return 5000 instead of 5 but this is the behavior if dot happens to be the thousand separator of the current culture.) – Mehrdad Afshari Oct 31 '09 at 22:57
  • Mehrdad- a very good answer. I think I actually learned about this practise (specifying the culture explicitly) from using FXCop. – RichardOD Oct 31 '09 at 22:59
  • I think that most programmers in other countries require understanding their importance, but it seems a lot of code out there is US based and contains a lot of culture arrogance. – Brett Ryan Oct 31 '09 at 23:01
  • @BrettRyan A very late comment but it is culture ignorance not arrogance :). – Jules Nov 15 '11 at 23:10
  • @Jules - if one writes software intended to be used by the world then it's arrogant, if they instead forget about other countries/locales entirely then it's ignorant. I think both apply, sometimes when you have a library that is not culture aware and you need it to be you may utter "arrogant so and so's" :) – Brett Ryan Nov 19 '11 at 06:59
4

Could be a locale problem. E.g. some countries use dots as date separators.

Edit: It is a locale problem. I just tried your format string on a machine with german locale and it is producing 2009.10.31

EricSchaefer
  • 25,272
  • 21
  • 67
  • 103
  • I agree, but surely when I say - return tempDateTime.ToString("yyyy/MM/dd:HH:mm:ss"); I mean give me that string regardless of locale? – JL. Oct 31 '09 at 22:44
  • ToString("yyyy/MM/dd:HH:mm:ss",System.Globalization.CultureInfo.InvariantCulture); – EricSchaefer Oct 31 '09 at 22:46