针对特定区域性格式化日期和时间

DateTime 结构提供了一些方法,使应用程序可以针对 DateTime 类型执行区分区域性的操作。 应用程序可以使用 DateTimeFormatInfo 类,根据区域性来格式化和显示 DateTime 类型。 例如,使用 DateTimeFormatInfo.ShortDatePattern,可以针对英语(美国)“en-US”区域性将日期 2001 年 2 月 1 日格式化为 2/1/2001,针对英语(英国)“en-GB”区域性将该日期格式化为 01/02/2001。

只能为特定区域性或固定区域性创建 DateTimeFormatInfo 对象,而不能为非特定区域性创建该对象。 非特定区域性不提供显示正确日期格式所需的足够信息。 如果应用程序尝试使用非特定区域性来创建 DateTimeFormatInfo 对象,将引发异常。 有关使用 DateTime 格式化的其他信息和示例,请参见日期和时间格式字符串

下面的代码示例使用 DateTimeFormatInfo.ShortDatePattern,在 Thread.CurrentThread 当前区域性分别设置为英语(美国)“en-US”和德语(德国)“de-DE”时显示当前日期。

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
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));
   }
}

如果在 2001 年 7 月 9 日执行这些代码,则输出结果为:

7/9/2001
09.07.2001

使用时区

DateTime 结构总是使用本地时区来执行计算和比较。 当应用程序使用 DateTime.ParseDateTime.ParseExact 方法时,您应该考虑这一点。 这些方法提供了重载,从而允许将日期和时间的字符串表示形式转换为 DateTime 类型。 应用程序还可以针对特定区域性来格式化 DateTime 类型。 如果没有在传递给这些方法的字符串中指定时区,则这些方法将检索经过分析的日期和时间,而不会执行时区调整。 日期和时间基于操作系统的时区设置。 如果应用程序指定了时区偏移量,则这些方法将分析日期/时间字符串,将其转换为协调世界时(UTC;以前称为格林尼治标准时间,即 GMT),然后将其转换为本地系统的时间。

应用程序应使用 DateTime.ToUniversalTime 方法将本地 DateTime 类型转换为它的 UTC 等效类型。 若要分析日期/时间字符串并将其转换为 UTC DateTime 类型,应用程序应将 DateTimeStyles.AdjustToUniversal 枚举值与 DateTime.Parse 方法或 DateTime.ParseExact 方法一起使用。

下面的代码示例针对本地时间创建了一个 DateTime 类型,然后将其转换为 UTC 等效类型。 这两种类型均转换为字符串并写到控制台。 请注意,由于本地时区和 UTC 之间存在 UTC 偏移量,因此字符串之间存在差异。 这些字符串被使用 DateTime.ParseExact 方法重新转换为 DateTime 类型。 若要捕获存储在 utcdt 中的时区信息,必须将 DateTimeStyles.AdjustToUniversal 值指定为 DateTime.ParseExact 方法的参数。 有关各个时区的 UTC 偏移量的更多信息,请参见 GetUtcOffset

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
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);
   }
}

此代码产生下列输出:

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

使用 DateTime 成员

使用 DateTime 结构时,应注意诸如 DateTime.Day 之类的成员是基于公历的。 即使应用程序更改当前日历或允许用户通过“控制面板”中的“区域和语言选项”更改日期和时间设置,仍将使用公历来执行 DateTime 方法的计算,这可以防止这些方法所执行的算法被用户设置破坏。 如果希望应用程序基于当前日历来执行区分区域性的日期和时间操作,则应用程序必须使用 DateTimeFormatInfo.Calendar 属性来调用 Calendar 类提供的方法,例如 Calendar.GetDayOfMonth。 有关 DateTime 成员和 DateTimeFormatInfo.Calendar 成员所检索的值之间的差异的示例,请参见使用特定区域性的日历

使用 DateTime 结构时,请注意 DateTime 类型是一个不可变的值。 因此,诸如 DateTime.AddDays 之类的方法将检索新的 DateTime 值,而不是对现有值进行递增。 下面的示例阐释了如何使用语句 dt = dt.AddDays(1) 将 DateTime 类型递增一天。

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
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"));

   }
}

如果在 2001 年 8 月 3 日执行这些代码,则输出结果为:

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

请参见

其他资源

编码和本地化

Date and Time Format Strings