On This Page
Overview and Description
Date formatting is not constant through out the world. Although each date basically displays the day, month, and year, their presentation order and separators vary greatly. In fact, there may be many differences between regions within the same country.
To help illustrate this, let's look at two basic date formats:
Long Date (Tuesday, October 12, 1954)
Now let's compare these formats between US-English, Mexican-Spanish, and Japanese.
English: Tuesday, October 12, 1954
Obviously, the names of the months and days of the week are different from locale to locale. However, there are other notable differences as well. In Spanish, the day comes before the month, everything is lowercase and the article "de" has been added. In Japanese, the day of the week is not displayed, and the translations for day, month and year act more like separators.
In the short date, we again see that in Spanish the order is day/month/year as compared to the US where it is month/day/year. In Japan, the order is year/month/day. This can cause sconfusion if not watched carefully. For example, depending on which country you are in, the date specified as 07/04/01 could mean:
English: July 4th, 2001
These examples shows why you should use the date APIs when dealing with dates. Not only will they handle the correct format, but they will also display the correct translations for the long dates, thus saving translation costs.
Figure 1: Available calendar types for the Korean locale
Table 1: Supported calendar types in Windows 2000 and Windows XP
Manipulating Calendars and Formatting Dates in Win32
The easiest and most efficient method of formatting the date in a way that is locale-aware is to use the GetDateFormat API. This API allows the formatting of any given date in any supported locale format, according to the currently selected default calendar type and date format. Here is a code sample that shows how this API works:
The result of this code's execution for English (United States) and English (Canada) is illustrated in Figure 2 below:
Figure 2: Long date formatted for English (United States) and English (Canada)
In more advanced date processing and display, you can use the lpFormat parameter of GetDateFormat to represent the date in any alternative formats that the current locale supports. The elements in Table 4-2 can be used to construct a format-picture string. If you use spaces to separate the elements in the format string, these spaces will appear in the same location in the output string. The letters must adhere to the casing conventions shown in Table 4-2. (For example, the correct formatting for "month as digits with leading zero for single-digit months" would be "MM" not "mm".) Characters in the format-picture string that are enclosed in single quotation marks will appear in the same location and will be unchanged in the output string.
Table 2: Date and time picture string elements
For example, to get the date string:
"Wed, Aug 31 94"
use the following picture string:
"ddd',' MMM dd yy"
You can also retrieve all standard date formats available for a given locale by using the EnumDateFormatsEx API. Here is how it works:
Execution of the previous code would give the following result in English (United States) and English (Canada) user locales, respectively. (See Figure 3 below)
Figure 3: Result of enumerating all long date formats for English (United States) and English (Canada) user locales
As you probably noticed in the last code sample, one of the arguments of the enumeration callback function for date formats is the calendar type (CALID). As mentioned earlier, for some locales more than one calendar type is available. For example, if the user locale is set to Hebrew, then the enumeration would return long-date formats for both Gregorian and Hebrew lunar calendars. For most of the applications, the basic functionality made available by GetDateFormat, which allows the date to be represented in the currently selected calendar and format, is enough. However, some applications might want to have more control over the way this information is presented and eventually select the calendar type in which the date is being displayed. There are several Win32 NLS APIs that allow you to manipulate calendar types.
The EnumCalendarInfoEx API can be used to enumerate all calendar information (such as names of calendars, names of days of the week, and names of months) for all applicable and available calendar types pertaining to a given locale. The code sample enumerates the native names of all supported calendars.
Execution of the previous code sample would give the following result on English (United States) and Arabic (Tunisia) user locales, respectively. (See Figure 4 below)
Figure 4: Result of enumerating calendar formats for English (United States) and Arabic (Tunisia) user locales
The GetLocaleInfo API with the LOCALE_ICALENDARTYPE flag also allows you to retrieve the default calendar type currently selected by the user. Once you have retrieved the calendar you want, you can use GetCalendarInfo to retrieve specific information about that particular calendar. This information includes the following:
In a nutshell, Win32 NLS APIs give your application full control over the way a date can be represented by letting you select a given calendar type and a given formatting type for that calendar. In fact, NLS APIs give you more flexibility than you would ever need. As stated earlier, GetDateFormat is probably enough to format dates in a way that is locale-aware.
In "Use Locale Model", you saw how to retrieve the current browser locale on the client side and how to set the global locale of your context or session to this value. Once the appropriate locale has been set, you can easily format dates using FormatDateTime in VBScript, a locale-aware function. Suppose you retrieve Spanish (Mexico) as the primary browser locale. ("es-MX" is the default value for this locale.) The following code saves the current context locale (matching the server's user locale), sets the locale to Spanish (Mexico), formats the date in Spanish (Mexico) format, and restores the original locale:
And the output would be:
Obviously, scripting technology does not offer the same flexibility to manipulate dates and calendars as NLS APIs do in the case of Win32 programming. However, the FormatDateTime function lets you display dates in the user's preferred culture, in both short-date and long-date formats.
Date and Calendar Formatting in the .NET Framework
The easiest and most efficient way of formatting dates in the .NET world is to take advantage of the DateTime structure, which provides methods allowing you to perform culture-sensitive operations on DateTime. Use the DateTimeFormatInfo class to format and display a DateTime based on a culture-specific standard. DateTimeFormatInfo defines how DateTime values are formatted and displayed, depending on the culture. For example, using the ShortDatePattern, the date April 24, 2001, is formatted as 4/24/2001 for the "en-US" culture and 24/04/2001 for the "en-GB"-English (United Kingdom)-culture.
An instance of DateTimeFormatInfo can be created for a specific culture, but not for a neutral culture. A neutral culture does not provide enough information to display the correct date format. You just saw that English (United States) and English (United Kingdom) share the same neutral culture-English-and yet have completely different formatting for the date.
The following code example displays the current date using the DateTimeFormatInfo.ShortDatePattern property when the CurrentThread.CurrentCulture is set to "en-US," and then to "de-DE" (German in Germany).
If you execute this code on April 24, 2001, the output appears as follows:
The table below lists the standard format characters for each standard pattern of formatting, and the associated DateTimeFormatInfo property that can be set to modify the standard pattern. The format characters are case-sensitive; for example, "g" and "G" represent slightly different patterns.
Table 3: List of DateTimeFormatInfo properties, patterns, and date formats for "en-US" format patterns. The format pattern varies according to culture.
In Thailand, the Gregorian and the Buddhist calendar coexist. Internally, however-similar to the Win32 paradigm-the .NET Framework handles dates in the Gregorian calendar by using data structures. Therefore, when you use the methods provided by the DateTime structure, you must be aware that the members such as the DateTime.Day property, the DateTime.Month property, the DateTime.Year property, and the DateTime.AddDays method are based on the Gregorian calendar. Even if you change the current calendar in your application's code or change date and time settings through the Regional and Language Options Control Panel, the Gregorian calendar is still used to perform the calculations for these methods. This functionality prevents the arithmetic performed by these methods from being corrupted by a user's settings. If you want to perform culture-sensitive date and time operations based on the current calendar, you must use the DateTimeFormatInfo.Calendar property to call methods provided by the Calendar class such as Calendar.GetDayOfMonth, Calendar.GetMonth, Calendar.GetYear, and Calendar.AddDays.
To handle native calendar types, the .NET Framework provides the Calendar class as well as the following Calendar implementations: GregorianCalendar, HebrewCalendar, HijriCalendar, JapaneseCalendar, JulianCalendar, KoreanCalendar, PersianCalendar, TaiwanCalendar, and ThaiBuddhistCalendar. Other things you can use include the CultureInfo class, which has a CultureInfo.Calendar property that specifies a culture's default calendar. The CultureInfo.OptionalCalendars property specifies the optional calendars supported by a culture.
The following code example in C# creates CultureInfo objects for the culture "th-TH" (Thai in Thailand) and displays the default and optional calendars for each culture. The GregorianCalendar is further divided into subtypes by the GregorianCalendar.CalendarType property. In this example, each time the calendar is determined to be Gregorian, the CalendarType value is retrieved and displayed.
This code produces the following output:
As you see, the .NET Framework offers a UI that's extensive, yet flexible and easy to use for date and calendar formatting. The sections that follow outline the points to consider when representing time in Win32 applications, Web pages, and the .NET Framework. Included is information on using the appropriate separators between hours, minutes, and seconds; constructing format-picture strings; and displaying time zones.
See MSDN documentation on: