Scott Hanselman

Enabling Evil - Overriding System.DateTime's default ToString

August 15, '06 Comments [5] Posted in Internationalization | Musings
Sponsored By

Had an interesting back and forth with Tom Wayson today. He wanted to be able to "modify the default behavior of DateTime.ToString()."

So, pushing aside issues of localization and the questions of "why would you want to do that?" let's look at the problem.

He has an intranet application and doesn't need to localize it. He wants to 'enforce' a specific date/time format and wants to avoid writing DateTime.Now.ToString("MM/dd/yy HH:mm:ss") everytime. He also doesn't want to explicitly set the system-wide settings in Control Panel | Regional Settings.

He noted that the output of DateTime.Now.ToString on a standard en-us machine in the states gave this output:

8/15/2006 3:27:27 PM

It looks like the output of ToString is the combination of the DateTimeFormatInfo.ShortDatePattern and DateTimeFormatInfo.ShortTimePattern. So, he: 

Imports System

Imports System.Globalization

 

Public Module MyModule

    Sub Main()

        Dim customCulture As CultureInfo = New CultureInfo("en-US")

        customCulture.DateTimeFormat.ShortDatePattern = "MM/dd/yy"

        'HH means 24 hour time, while hh means 12 hour time
        customCulture.DateTimeFormat.ShortTimePattern = "HH:mm:ss"

 

        System.Threading.Thread.CurrentThread.CurrentCulture = customCulture

        System.Threading.Thread.CurrentThread.CurrentUICulture = customCulture

 

        WL(DateTime.Now.ToString())

        WL(DateTime.Now.ToShortDateString())

        WL(DateTime.Now.ToShortTimeString())

    End Sub

 

    Sub WL(ByVal text As Object)

        Console.WriteLine(text)

    End Sub

End Module 

But the output was still 12 hour time:

8/15/06 3:28:34 PM

Ah...a little Reflectoring shows us that the default format string for System.DateTime is "G" as in System.DateTime.ToString("G") where G is one of the presets.

From PowerShell we see:

PS>C:\Documents and Settings\shanselm\Desktop
[DateTime]::Now.ToString("g")
8/15/2006 3:28 PM
PS>C:\Documents and Settings\shanselm\Desktop
[DateTime]::Now.ToString("G")
8/15/2006 3:28:02 PM
PS>C:\Documents and Settings\shanselm\Desktop
[DateTime]::Now.ToString()
8/15/2006 3:28:15 PM

So we add:

Imports System

Imports System.Globalization

 

Public Module MyModule

    Sub Main()

        Dim customCulture As CultureInfo = New CultureInfo("en-US")

        customCulture.DateTimeFormat.ShortDatePattern = "MM/dd/yy"

        'HH means 24 hour time, while hh means 12 hour time
        customCulture.DateTimeFormat.ShortTimePattern = "HH:mm:ss"       
        customCulture.DateTimeFormat.LongTimePattern = "HH:mm:ss"

 

        System.Threading.Thread.CurrentThread.CurrentCulture = customCulture

        System.Threading.Thread.CurrentThread.CurrentUICulture = customCulture

 

        WL(DateTime.Now.ToString())

        WL(DateTime.Now.ToShortDateString())

        WL(DateTime.Now.ToShortTimeString())

    End Sub

 

    Sub WL(ByVal text As Object)

        Console.WriteLine(text)

    End Sub

End Module 

And gets the output he expects, indicating that "G" is the combination of a ShortDate and a LongTime.

8/15/2006 15:28:57

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Wednesday, August 16, 2006 2:16:07 AM UTC
There is an existing DateTimeFormatInfo, DateTimeFormatInfo.InvariantCulture, that has a similar format. If you want to use it (and not change the rest of your CurrentCulture):

CultureInfo customCulture = new CultureInfo(Thread.CurrentThread.CurrentCulture.Name);
customCulture.DateTimeFormat = DateTimeFormatInfo.InvariantInfo;

Thread.CurrentThread.CurrentCulture = customCulture;

string sNow = DateTime.Now.ToString();

This will output the same string that you have. But honestly, you should pass DateTimeFormatInfo.InvariantInfo to ToString() explicitly, and then you don't have to go about mangling the thread's cultureinfo. While you're at it, this thing is going across the wire? Maybe you ought to use UTC and a format that round trips.

string sNow = DateTime.UtcNow.ToString("u", DateTimeFormatInfo.InvariantInfo);

it comes out the other side...

DateTime dNow = DateTime.Parse(sNow, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.RoundtripKind);
DateTime dLocal = dNow.ToLocalTime();

c
chris
Wednesday, August 16, 2006 7:39:33 AM UTC
Dude, you're preaching to the converted. That's why the post was called "Enabling Evil" and had the disclaimers at the top explaining the constraint that the guy had - he wanted to change the behavior of EXISTING ToString() calls.
Scott Hanselman
Wednesday, August 16, 2006 2:06:19 PM UTC
Glad to hear I'm not the only developer being forced to do this. Our customer comes with alot of red tape. They want their dates formatted 'dd MMM yyyy'. At first they mandated that all dates be run through a SQL user-defined function called 'PrepareDate(date)' before being displayed. I was able to convince them that a round trip to their SQL server for each date was a bad idea, and we compromised on a similar solution, overriding the default short date format as above.

We're now migrating to 2.0, though, and may be able to sneak a proper fix in. So what would be the "right" way to do this? A custom culture? It will need to work with databinding- ie setting the format string to {0:d} or similar...
Wednesday, August 16, 2006 3:16:21 PM UTC
Scott, I find your comments about changing default behavior ('evil') interesting in light of our email conversation a week or two ago, regarding the of Object.prototype in JavaScript . . . (You know, the one where you asked me "Why isn't it a good thing? It works...").

;)

Wednesday, August 16, 2006 3:17:07 PM UTC
Last comment should have read like this:


Scott, I find your comments about changing default behavior ('evil') interesting in light of our email conversation a week or two ago, regarding the hacking of Object.prototype in JavaScript . . . (You know, the one where you asked me "Why isn't it a good thing? It works...").

;)

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.