Although there are several ways in ASP.Net to influence the way DateTimes are displayed some methods are better than others and some are evil.
The easiest way to display DateTime and have some influence on them, is to specify the culture and the uiCulture in the globalization tag in the web.config. This is the preferred way if you can use the default date/time formats in that culture.
Example:
<%=DateTime.Now %> is rendered as "16-8-2006 10:14:49" with this globalization tag <globalization uiCulture="nl-NL" culture="nl-NL" /> and rendered as "8/16/2006 10:18:37" with the culture and uiCulture set to en-US.
If you want a little more control, or when the default date/time formats don't offer enough flexibility you can specify a format in the ToString method of the DateTime object. This will still use the culture specified in the web.config for the (abbreviated) names of the months. The downside to this method is that you have to remember to set the correct format string, every time you want to display a date/time.
Example:
<%=DateTime.Now.ToString( "dd MMM \\'yy" )%> is rendered as "16 août '06" with the culture set to fr-FR ( the \\ are required for escaping the ' ).
When you want to offer your users a localized version of your web-application, you can't rely on the globalization settings in the web.config, instead you'll have to either set the Culture and UICulture of the current executing thread or use one of the ToString overrides that accepts an IFormatProvider. When you only specify an IFormatProvider, the default (or G) format is used to render the string and although you can override the default format, that is generally considered evil.
Example:
<%=DateTime.Now.ToString( new System.Globalization.CultureInfo("es-ES")) %> is rendered as "16/08/2006 11:43:11", while <%=DateTime.Now.ToString("dd MMM \\'yy", new System.Globalization.CultureInfo("es-ES")) %> is rendered as "16 ago '06".
These methods were the only methods that were available on version 1.x of the .Net framework. In .Net 2.0 you have the ability to define a custom culture using the CultureAndRegionInfoBuilder class. After creating a new culture, this new culture can be installed on a computer and used by any application on that computer. This allows all (web-)applications on that computer to use the same formatting for dates, and numbers, casing etc. This way you can change the default format for string rendering in a less evil way.
Example:
First setup the custom culture using a console application, since this requires administrator rights.
class Program{
static void Main( string[] args ) {
if (args.Length == 0 || args[0].EndsWith("i", StringComparison.OrdinalIgnoreCase)) {
RegisterNewRegion();
Console.WriteLine("Registered new region \"x-en-US-custom\".");
} else if (args[0].EndsWith("u", StringComparison.OrdinalIgnoreCase)) {
UnRegisterNewRegion();
Console.WriteLine("Unregistered new region \"x-en-US-custom\".");
} else {
Console.WriteLine("use /i to register and /u for unregister.");
}
Console.WriteLine("Press enter.");
Console.ReadLine();
}
static void RegisterNewRegion() {
// instantiate a new CultureAndRegionInfoBuilder object named x-en-US-demo
CultureAndRegionInfoBuilder cib = new CultureAndRegionInfoBuilder("x-en-US-custom", CultureAndRegionModifiers.None);
//load the culture data from the default en-US culture and region
cib.LoadDataFromCultureInfo(new CultureInfo("en-US"));
cib.LoadDataFromRegionInfo(new RegionInfo("US"));
// set the custom date/time format
cib.GregorianDateTimeFormat.ShortDatePattern = "dd-MM-yy";
cib.GregorianDateTimeFormat.LongDatePattern = "dd MMM \\'yy";
cib.GregorianDateTimeFormat.ShortTimePattern = "HH:mm";
cib.GregorianDateTimeFormat.LongTimePattern = "HH:mm";
// register the culture
cib.Register();
}
static void UnRegisterNewRegion() {
CultureAndRegionInfoBuilder.Unregister("x-en-US-custom");
}
}
Now you can use your custom culture in any web-application, like the previous examples.
<%=DateTime.Now %> is rendered as "16-8-2006 10:14:49" with this globalization tag <globalization uiCulture="x-en-US-custom" culture="x-en-US-custom" />
Another use would be for writing dates to a log-file, when you need to sort or parse them in future.
Thanks to michkap from Sorting It All Out for the tip on CultureAndRegionInfoBuilder and the post that inspired this post.