Skip to main content

Globalization Step-by-Step


Time Formatting

*

Overview and Description

Like date and calendar formats, time formats are not constant throughout the world. Although each representation of time basically displays the hour, minutes, and seconds, their presentation order and separators vary greatly. In fact, there might be many differences between regions within the same country. The time formatting might differ from one culture to another in one of the following three ways:

  1. The use of either a 12-hour or 24-hour clock.
    Most European and Asian locales use the 24-hour clock instead of the 12-hour A.M./P.M. model used in the United States. Also, A.M./P.M. can be rendered in the language of the country, and in some languages comes before the time and not after it.
  2. The character used to separate hours, minutes, and seconds.
    Although the colon (:) is the character most used in separating the hours, minutes, and seconds, some Asian languages use ideographic characters. In addition, some locales require "h," "m," and "s" as part of the display.
  3. The storage and display of time zones.
    One way that's frequently used to represent the time zone is to display GMT (Greenwich Mean Time) or its modern replacement UTC (Coordinated Universal Time) as the base. This is then followed by the time zone, which is indicated as a positive or negative offset in hours and minutes. (Some time zones use 30-minute or 45-minute offsets.) For example, the time zone for Bengaluru, India, would be displayed as UTC +5:30, and for Chatham Island, New Zealand, it would be UTC +12:45. Another way to display time zones is by using names for the local time zones. If you do so, you must take the following into account:
    • Not all countries use local names.
    • Time-zone abbreviations are not unique.
    • Not all countries use daylight saving time, and daylight saving time does not start and end on the same day in every country.
    • One time zone might have many different names, depending on the country and the language.

Important: Changing the user locale or the locale variable does not adjust the time zone by default.

Figure 1: Time formatting for Greek user locale.

Figure 1: Time formatting for Greek user locale.


 
Figure 2: Time Zone page of Date And Time Properties property sheet.

Figure 2: Time Zone page of Date And Time Properties property sheet.


 

Top of pageTop of page

Time Formatting and Time Zones in Win32

To format time in the default settings of a given locale or as specified by the user in the Regional and Language Options Control Panel, you can use GetTimeFormat. This function formats time--either a specified time or the local system time--as a time string for a specified locale.

The following code sample displays the current system time for the current user locale, using the default time format for that locale:

 

// Formats time as a time string for a specified locale.

GetTimeFormat(LOCALE_USER_DEFAULT, // predefined current user locale
0, // option flag for things like no usage of seconds or
// force 24h clock
NULL, // time - NULL to go with the current system locale time
NULL, // time format string - NULL to go with default locale
// format
g_szBuff1, // formatted string buffer
MAX_STR); // size of string buffer

Execution of this code would give the following result on English (United States) and Punjabi user locales, respectively. (See Figure 3 below)

Figure 3: Time formatted for English (United States) and Punjabi user locales

Figure 3: Time formatted for English (United States) and Punjabi user locales


As you saw in the previous example, the time formatting can be completely different from one locale to another. In this case, the use of a leading 0 in the hour representation, as well as the actual translation and positioning of P.M., change based on country and cultural standards. But even within the same locale or culture there is a variety of possible ways to format time: short or long formatting. The EnumTimeFormats function enumerates the time formats that are available for a specified locale. It does so by passing (to a callback function that an application defines) a pointer to a buffer that contains a time format. The EnumTimeFormats continues to do so until no more time formats are found, or until the callback function returns FALSE. Here is how the code works:

EnumTimeFormats(EnumTimeFormatsProc, // enumeration callback function
LOCALE_USER_DEFAULT, // locale for which the enumeration is done
NULL); // unused

 

// The callback function...
BOOL CALLBACK EnumTimeFormatsProc(LPTSTR lpTimeFormatString)
{
// end of enumeration, then terminate
if (!lpTimeFormatString)
return FALSE;
MessageBox(NULL, g_lpTimeFormatString, TEXT("Available Time format"), MB_OK);
return TRUE;
}

Execution of this code would give the following result on English (United States) and French (France) user locales, respectively. (See Figure 4 below.)

Figure 4: Time formats for English (United States) and French (France) user locales

Figure 4: Time formats for English (United States) and French (France) user locales


 

The obtained result (format picture) can then be used as an lpFormat argument in a call to GetTimeFormat. This allows you to use an alternative formatting for the time. The following elements can be used to construct a format-picture string. (See Table 1 below.) 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 the table. (For example, the correct formatting for "Seconds with leading zero for single-digit seconds" would be "ss" not "SS".) Characters in the format string that are enclosed in single quotation marks will appear in the same location and will be unchanged in the output string.

Table 1: Elements for constructing a format-picture string.


 

For example, to get the time string:

"11:29:40 PM"


use the following picture string:

"hh':'mm':'ss tt"


To retrieve information regarding the time parameters for a particular time zone that the user has selected, you can use the GetTimeZoneInformation function. These parameters control the translations between UTC and local time.

DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation);

 

// Where LPTIME_ZONE_INFORMATION is defined as:

 

typedef struct _TIME_ZONE_INFORMATION
{
LONG Bias;
WCHAR StandardName[ 32 ];
SYSTEMTIME StandardDate;
LONG StandardBias;
WCHAR DaylightName[ 32 ];
SYSTEMTIME DaylightDate;
LONG DaylightBias
}
TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION;

The Bias parameter of the TIME_ZONE_INFORMATION structure is the difference, in minutes, between UTC time and local time.

All translations between UTC time and local time are based on the following formula:

UTC = local time + bias

Unfortunately, Win32 APIs do not offer a solution to enumerate information relative to any other time zone than the one currently selected by the user. GetLocalTime and GetSystemTime will allow you to retrieve the current local and the UTC times, respectively. To convert the local time to UTC, you can use the LocalFileTimeToFileTime API. These are but two of the many Win32 APIs dealing with time. To learn about other functions, search for "time functions" on http://msdn2.microsoft.com.

Top of pageTop of page

Time Formatting and Time Zones in .NET Framework

The easiest and most efficient way of doing time formatting in the .NET world is to take advantage of the DateTime structure that provides methods such as DateTime.ToString and DateTime.Parse. These methods allow you to perform culture-sensitive operations on a DateTime object. Use the DateTimeFormatInfo class to format and display a DateTime based on culture. DateTimeFormatInfo defines how DateTime values are formatted and displayed, depending on the culture. For example, using the LongTimePattern, the time 4 hours P.M., 36 minutes and 15 seconds is formatted as 4:36:15 PM for the "en-US" culture and 16:36:15 for the "fr-FR" culture number-formatting standards. (For more information and code samples, see the Date Formatting article.)

Methods and properties in the DateTime structure always use the local time zone for calculations and comparisons. You should consider this when using the DateTime.Parse method and the DateTime.ParseExact method. These methods provide overloads that allow you to convert the string representation of a date and time to a DateTime type. You can also choose to format a DateTime for a specific culture. If you do not specify a time zone in the string that you pass to these methods, they return the parsed date and time without performing a time-zone adjustment. The date and time are based on the system's time-zone setting. If you specify a time-zone offset, these methods parse the date/time string, convert it to UTC, and then convert it to the time on the local system.

Use the DateTime.ToUniversalTime method to convert a local DateTime to its UTC equivalent. To parse a date/time string and convert it to a UTC DateTime, use the DateTimeStyles enumeration AdjustToUniversal value with either the DateTime.Parse or DateTime.ParseExact method. These DateTime manipulations are illustrated in the following code example. This example creates a DateTime for the local time and then converts it to the UTC equivalent DateTime. Both types are converted to strings and written to the console. Notice that the strings differ by the UTC offset between the local time zone and UTC. (For more information on the UTC offset for various time zones, see the TimeZone.GetUtcOffset method in the Microsoft Developer Network documentation at http://msdn2.microsoft.com.) These strings are converted back to DateTime types using the DateTime.ParseExact method. To capture the time-zone information stored in utcdt, the AdjustToUniversal value must be specified as a parameter to the DateTime.ParseExact method.

using System;
using System.Globalization;
using System.Threading;

public class TimeZoneSample
{

 

public static void Main()
{
CultureInfo en = new CultureInfo("en-US");
Thread.CurrentThread.CurrentCulture = en;

 

// Create a DateTime object for the local time.
DateTime dt = new DateTime(2001, 7, 13, 4, 0, 0);

 

// Convert the local DateTime to the UTC time.
DateTime utcdt = dt.ToUniversalTime();

 

// Define a custom string format to display the DateTime
// value. zzzz specifies the full time zone offset.
String format = "MM/dd/yyyy hh:mm:sszzz";

 

// Convert the local DateTime object to a string
// using the custom format string and display.
String str = dt.ToString(format);
Console.WriteLine(str);

 

// Convert the UTC DateTime to a string
// using the custom format string and display.
String utcstr = utcdt.ToString(format);
Console.WriteLine(utcstr);

 

// Convert the string back to a local DateTime object and
// display.
DateTime parsedBack = DateTime.ParseExact(str,format,en.DateTimeFormat);
Console.WriteLine(parsedBack);

 

// Convert the string back to a UTC DateTime object and
// display. If you do not use the DateTime.ParseExact
// method that takes a DateTimeStyles.AdjustToUniversal
// value, the parsed DateTime object will not include the
// time zone information.

 

DateTime parsedBackUTC = DateTime.ParseExact _
(str, format, en.DateTimeFormat, DateTimeStyles.AdjustToUniversal);
Console.WriteLine(parsedBackUTC);
}
}

This code produces the following output:

07/13/2001 04:00:00-07:00
07/13/2001 11:00:00-07:00
7/13/2001 4:00:00 AM
7/13/2001 11:00:00 AM

Another vital point to consider when creating an application that is locale-aware is how currency is displayed. Since money is a valued commodity, it is essential that such things as the correct currency symbol as well as the appropriate decimal and thousands separator be used, for example, or the consequences could potentially be disastrous!

Top of pageTop of page

Time Formatting in Web Pages

In "Retrieving the Browser Language Setting" in the Use Locale Model article, 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. After the appropriate locale has been set, you can easily format the time using FormatDateTime, a locale-aware function. Suppose you have retrieved the Chinese (Taiwan) locale as the primary browser locale ("zh-TW" 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 Chinese (Taiwan), formats the date in Chinese (Taiwan) format, and restores the original locale.

currentLocale = GetLocale
Original = SetLocale("zh-TW")
DateData = FormatDateTime(Now(),vbLongTime)
Original = SetLocale(currentLocale)

And the output would be:

下午 04:16:08

Obviously the scripting technology does not offer the same flexibility to manipulate time formats as NLS APIs do in the case of Win32 programming. However, the FormatDateTime function gives you the ability to display time in the user's cultural preferences in both short- and long-time formats.

Top of pageTop of page

References

See the MSDN documentation for details about the following APIs:
EnumTimeFormats
GetTimeFormat
GetTimeZoneInformation
SetTimeZoneInformation
DateTime Structure for .NET

 

 

Top of pageTop of page Previous5 of 11 Next