如何:枚举计算机上的时区

若要成功使用指定的时区,需要该时区的相关信息可供系统使用。 Windows XP 和 Windows Vista 操作系统将此信息存储在注册表中。 但是,尽管世界上存在的时区总数非常大,但注册表包含的信息只是其中的一个子集。 此外,注册表本身是一个动态结构,其内容可能发生有意或无意的更改。 因此,应用程序无法保证系统上始终存在已定义且可用的特定时区。 对于使用时区信息应用程序的许多应用程序来说,第一步是确定所需时区在本地系统上是否可用,或者向用户提供可供选择的时区列表。 这要求应用程序枚举本地系统上定义的时区。

注意

如果应用程序依赖于可能不是在本地系统上定义的特定时区,则该应用程序可通过序列化和反序列化有关时区的信息来确保其存在。 然后,可将相关时区添加到列表控件,使应用程序用户可以选择该时区。 有关详细信息,请参阅如何:将时区保存到嵌入的资源如何:从嵌入的资源还原时区

枚举本地系统上存在的时区

  1. 调用 TimeZoneInfo.GetSystemTimeZones 方法。 该方法会返回 TimeZoneInfo 对象的泛型 ReadOnlyCollection<T> 集合。 集合中的项按其 DisplayName 属性排序。 例如:

    ReadOnlyCollection<TimeZoneInfo> tzCollection;
    tzCollection = TimeZoneInfo.GetSystemTimeZones();
    
    Dim tzCollection As ReadOnlyCollection(Of TimeZoneInfo) = TimeZoneInfo.GetSystemTimeZones
    
  2. 枚举集合中的各个 TimeZoneInfo 对象,方法是使用 foreach 循环(在 C# 中)或 For Each...Next 循环(在 Visual Basic 中),然后对每个对象进行任何必要处理。 例如,以下代码枚举步骤 1 中返回的 TimeZoneInfo 对象的 ReadOnlyCollection<T> 集合,并在控制台上列出每个时区的显示名称。

    foreach (TimeZoneInfo timeZone in tzCollection)
        Console.WriteLine($"   {timeZone.Id}: {timeZone.DisplayName}");
    
    For Each timeZone As TimeZoneInfo In tzCollection
        Console.WriteLine("   {0}: {1}", timeZone.Id, timeZone.DisplayName)
    Next
    

向用户提供本地系统上存在的时区列表

  1. 调用 TimeZoneInfo.GetSystemTimeZones 方法。 该方法会返回 TimeZoneInfo 对象的泛型 ReadOnlyCollection<T> 集合。

  2. 将步骤 1 中返回的集合分配给 Windows 窗体或 ASP.NET 列表控件的 DataSource 属性。

  3. 检索用户已选择的 TimeZoneInfo 对象。

该示例提供了 Windows 应用程序的说明。

示例

该示例将启动一个 Windows 应用程序,其中显示了以列表框在系统上定义的时区。 然后,该应用程序会显示一个对话框,其中包含用户所选时区对象的属性 DisplayName 的值。

private void Form1_Load(object sender, EventArgs e)
{
    ReadOnlyCollection<TimeZoneInfo> tzCollection;
    tzCollection = TimeZoneInfo.GetSystemTimeZones();
    _timeZoneList.DataSource = tzCollection;
}

private void OkButton_Click(object sender, EventArgs e)
{
    TimeZoneInfo? selectedTimeZone = (TimeZoneInfo?)_timeZoneList.SelectedItem;
    MessageBox.Show($"You selected the {selectedTimeZone?.ToString()} time zone.");
}
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim tzCollection As ReadOnlyCollection(Of TimeZoneInfo)
    tzCollection = TimeZoneInfo.GetSystemTimeZones()
    Me.timeZoneList.DataSource = tzCollection
End Sub

Private Sub OkButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OkButton.Click
    Dim selectedTimeZone As TimeZoneInfo = DirectCast(Me.timeZoneList.SelectedItem(), TimeZoneInfo)
    MsgBox("You selected the " & selectedTimeZone.ToString() & " time zone.")
End Sub

大多数列表控件(如 System.Windows.Forms.ListBoxSystem.Web.UI.WebControls.BulletedList 控件)使你可以将对象变量的集合分配给其 DataSource 属性,只要该集合实现 IEnumerable 接口即可。 (泛型 ReadOnlyCollection<T> 类执行此操作。)若要在集合中显示单个对象,控件将调用该对象的 ToString 方法来提取用于表示对象的字符串。 对于 TimeZoneInfo 对象,ToString 方法返回 TimeZoneInfo 对象的显示名称(其 DisplayName 属性的值)。

注意

由于列表控件调用对象的 ToString 方法,因此你可以将 TimeZoneInfo 对象的集合分配给控件,使控件为每个对象显示有意义的名称,并检索用户已选择的 TimeZoneInfo 对象。 这样就无需为集合中的每个对象提取字符串,将字符串分配给一个集合(该集合反过来会分配给该控件的 DataSource 属性),检索该用户选定的字符串,然后使用此字符串提取它所描述的对象。

编译代码

此示例需要:

另请参阅