Formatting Date and Time for a Specific Culture

The DateTime structure provides methods such as DateTime.ToString and DateTime.Parse that allow you to perform culture-sensitive operations on a DateTime. 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 ShortDatePattern, the date February 1, 2001 is formatted as 2/1/2001 for the "en-US" culture and 01/02/2001 for the "en-GB" culture.

An instance of DateTimeFormatInfo can be created for a specific culture, or the invariant culture, but not for a neutral culture. A neutral culture does not provide enough information to display the correct date format. An exception is thrown if you attempt to create an instance of DateTimeFormatInfo using a neutral culture. For additional information and examples of using DateTime formatting, see Date and Time Format Strings.

The following code example displays the current date using the DateTimeFormatInfo.ShortDatePattern when the CurrentThread.CurrentCulture is set to "en-US", English in the United States, and then to "de-DE", German in Germany.

Imports System
Imports System.Globalization
Imports System.Threading

Public Class FormatDate
   
   Public Shared Sub Main()
      Dim dt As DateTime = DateTime.Now
      ' Sets the CurrentCulture property to U.S. English.
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      ' Displays dt, formatted using the ShortDatePattern
      ' and the CurrentThread.CurrentCulture.
      Console.WriteLine(dt.ToString("d"))
      
      ' Creates a CultureInfo for German in Germany.
      Dim ci As New CultureInfo("de-DE")
      ' Displays dt, formatted using the ShortDatePattern
      ' and the CultureInfo.
      Console.WriteLine(dt.ToString("d", ci))
   End Sub
End Class
[C#]
using System;
using System.Globalization;
using System.Threading;

public class FormatDate
{
   public static void Main()
   {
      DateTime dt = DateTime.Now;
      // Sets the CurrentCulture property to U.S. English.
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      // Displays dt, formatted using the ShortDatePattern
      // and the CurrentThread.CurrentCulture.
      Console.WriteLine(dt.ToString("d"));
      
      // Creates a CultureInfo for German in Germany.
      CultureInfo ci = new CultureInfo("de-DE");
      // Displays dt, formatted using the ShortDatePattern
      // and the CultureInfo.
      Console.WriteLine(dt.ToString("d", ci));
   }
}

If you execute this code on July 9, 2001, the output appears as follows:

7/9/2001
09.07.2001

Working with Time Zones

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 coordinated universal time (UTC; previously known as Greenwich Mean Time (GMT)), 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 Coordinated Universal Time (UTC). For more information about the UTC offset for various time zones, see TimeZone.GetUtcOffset Method. These strings are converted back to DateTime types using the DateTime.ParseExact method. Note that in order to capture the time zone information stored in utcdt, the AdjustToUniversal value must be specified as a parameter to the DateTime.ParseExact method.

Imports System
Imports System.Globalization
Imports System.Threading

Public Class TimeZoneSample
   Public Shared Sub Main()
      Dim en As New CultureInfo("en-US")
      Thread.CurrentThread.CurrentCulture = en

      ' Creates a DateTime for the local time.
      Dim dt As New DateTime(2001, 7, 13, 4, 0, 0)

      ' Converts the local DateTime to the UTC time.
      Dim utcdt As DateTime = dt.ToUniversalTime()

      ' Defines a custom string format to display the DateTime.
      ' zzz specifies the full time zone offset.
      Dim format As [String] = "MM/dd/yyyy hh:mm:sszzz"

      ' Converts the local time to a string
      ' using the custom format string and display.
      Dim str As [String] = dt.ToString(format)
      Console.WriteLine(str)

      ' Converts the UTC time to a string
      ' using the custom format string and display.
      Dim utcstr As [String] = utcdt.ToString(format)
      Console.WriteLine(utcstr)

      ' Converts the string back to a local DateTime and displays it.
      Dim parsedBack As DateTime = DateTime.ParseExact(str, format, 
            en.DateTimeFormat)
      Console.WriteLine(parsedBack)

      ' Converts the string back to a UTC DateTime and displays it.
      ' If you do not use the DateTime.ParseExact method that takes
      ' a DateTimeStyles.AdjustToUniversal value, the parsed DateTime
      ' will not include the time zone information. 
      Dim parsedBackUTC As DateTime = DateTime.ParseExact(str, format, _
            en.DateTimeFormat, DateTimeStyles.AdjustToUniversal)
      Console.WriteLine(parsedBackUTC)
   End Sub
End Class
[C#]
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;

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

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

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

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

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

      // Converts the string back to a local DateTime and displays it.
      DateTime parsedBack =
            DateTime.ParseExact(str,format,en.DateTimeFormat);
      Console.WriteLine(parsedBack);

      // Converts the string back to a UTC DateTime and displays it.
      // 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

Working with DateTime Members

When you use the methods provided by the DateTime structure, you must be aware that the members such as DateTime.Day, DateTime.Month, DateTime.Year, and DateTime.AddDays 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 Options dialog box in 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. For an example of the difference in values returned by the DateTime members and the Calendar class members, see Using Calendars for Specific Cultures.

When working with the DateTime structure, be aware that a DateTime is a value type and is immutable. Therefore, operations such as DateTime.AddDays return a new DateTime value instead of incrementing an existing value. The following example illustrates how to increment a DateTime by a day using the statement dt = dt.AddDays(1).

Imports System
Imports System.Globalization
Imports System.Threading
Imports Microsoft.VisualBasic

Public Class TestClass
   
   Public Shared Sub Main()
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      
      Dim dt As DateTime = DateTime.Now
      Console.WriteLine(ControlChars.Newline + " Today is {0}", _
         DateTime.Now.ToString("d"))
      
      ' Increments dt by one day.
      dt = dt.AddDays(1)
      Console.WriteLine(ControlChars.Newline + " Tomorrow is {0}", _
         dt.ToString("d"))
   End Sub
End Class
[C#]
using System;
using System.Globalization;
using System.Threading;

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

      DateTime dt = DateTime.Now;
      Console.WriteLine("Today is {0}", DateTime.Now.ToString("d"));

      // Increments dt by one day.
      dt = dt.AddDays(1);
      Console.WriteLine("Tomorrow is {0}", dt.ToString("d"));

   }
}

If you execute this code on August 3, 2001, it displays the following output:

Today is 8/3/2001
Tomorrow is 8/4/2001

See Also

Developing World-Ready Applications | Date and Time Format Strings | DateTime