如何:让用户解决不明确的时间
不明确的时间是指映射到多个协调世界时 (UTC) 的时间。 当向回调整时钟时间时(例如某时区在从夏时制转换为标准时间的过程中),就会出现此情况。 在处理不明确的时间时,可执行下列操作之一:
如果该不明确的时间是用户输入的数据项,则可将这种多义性留给用户解决。
就时间映射到 UTC 的方式进行假设。 例如,可以假定某个不明确的时间始终表示为时区的标准时间。
本主题介绍如何让用户解决不明确的时间。
让用户解决不明确的时间
获取用户输入的日期和时间。
调用 IsAmbiguousTime 方法以确定时间是否明确。
如果时间不明确,请调用 GetAmbiguousTimeOffsets 方法以检索 TimeSpan 对象的数组。 该数组中的每个元素都包含不明确的时间可以映射到的一个 UTC 偏移量。
让用户选择所需的偏移量。
通过从本地时间中减去用户选择的偏移量来得到 UTC 日期和时间。
调用 static(在 Visual Basic .NET 中为 Shared)SpecifyKind 方法,将 UTC 日期和时间值的 Kind 属性设置为 DateTimeKind.Utc。
示例
下面的示例提示用户输入一个日期和时间;如果输入的值不明确,则让用户选择不明确的时间映射到的 UTC 时间。
Private Sub GetUserDateInput()
' Get date and time from user
Dim inputDate As Date = GetUserDateTime()
Dim utcDate As Date
' Exit if date has no significant value
If inputDate = Date.MinValue Then Exit Sub
If TimeZoneInfo.Local.IsAmbiguousTime(inputDate) Then
Console.WriteLine("The date you've entered is ambiguous.")
Console.WriteLine("Please select the correct offset from Universal Coordinated Time:")
Dim offsets() As TimeSpan = TimeZoneInfo.Local.GetAmbiguousTimeOffsets(inputDate)
For ctr As Integer = 0 to offsets.Length - 1
Dim zoneDescription As String
If offsets(ctr).Equals(TimeZoneInfo.Local.BaseUtcOffset) Then
zoneDescription = TimeZoneInfo.Local.StandardName
Else
zoneDescription = TimeZoneInfo.Local.DaylightName
End If
Console.WriteLine("{0}.) {1} hours, {2} minutes ({3})", _
ctr, offsets(ctr).Hours, offsets(ctr).Minutes, zoneDescription)
Next
Console.Write("> ")
Dim selection As Integer = CInt(Console.ReadLine())
' Convert local time to UTC, and set Kind property to DateTimeKind.Utc
utcDate = Date.SpecifyKind(inputDate - offsets(selection), DateTimeKind.Utc)
Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString())
Else
utcDate = inputDate.ToUniversalTime()
Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString())
End If
End Sub
Private Function GetUserDateTime() As Date
Dim exitFlag As Boolean = False ' flag to exit loop if date is valid
Dim dateString As String
Dim inputDate As Date = Date.MinValue
Console.Write("Enter a local date and time: ")
Do While Not exitFlag
dateString = Console.ReadLine()
If dateString.ToUpper = "E" Then exitFlag = True
If Date.TryParse(dateString, inputDate) Then
exitFlag = true
Else
Console.Write("Enter a valid date and time, or enter 'e' to exit: ")
End If
Loop
Return inputDate
End Function
private void GetUserDateInput()
{
// Get date and time from user
DateTime inputDate = GetUserDateTime();
DateTime utcDate;
// Exit if date has no significant value
if (inputDate == DateTime.MinValue) return;
if (TimeZoneInfo.Local.IsAmbiguousTime(inputDate))
{
Console.WriteLine("The date you've entered is ambiguous.");
Console.WriteLine("Please select the correct offset from Universal Coordinated Time:");
TimeSpan[] offsets = TimeZoneInfo.Local.GetAmbiguousTimeOffsets(inputDate);
for (int ctr = 0; ctr < offsets.Length; ctr++)
{
Console.WriteLine("{0}.) {1} hours, {2} minutes", ctr, offsets[ctr].Hours, offsets[ctr].Minutes);
}
Console.Write("> ");
int selection = Convert.ToInt32(Console.ReadLine());
// Convert local time to UTC, and set Kind property to DateTimeKind.Utc
utcDate = DateTime.SpecifyKind(inputDate - offsets[selection], DateTimeKind.Utc);
Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString());
}
else
{
utcDate = inputDate.ToUniversalTime();
Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString());
}
}
private DateTime GetUserDateTime()
{
bool exitFlag = false; // flag to exit loop if date is valid
string dateString;
DateTime inputDate = DateTime.MinValue;
Console.Write("Enter a local date and time: ");
while (! exitFlag)
{
dateString = Console.ReadLine();
if (dateString.ToUpper() == "E")
exitFlag = true;
if (DateTime.TryParse(dateString, out inputDate))
exitFlag = true;
else
Console.Write("Enter a valid date and time, or enter 'e' to exit: ");
}
return inputDate;
}
该代码示例的核心使用 TimeSpan 对象的数组指示不明确时间的各个可能的 UTC 偏移量。 但是,这些偏移量对用户不可能有意义。 为了阐明偏移量的含义,该代码还通过注释说明了偏移量表示的是本地时区的标准时间还是其夏时制。 该代码通过将偏移量与 BaseUtcOffset 属性的值进行比较来确定哪个时间是标准时间,哪个时间是夏时制时间。 此属性指示 UTC 与时区标准时间之差。
在此示例中,本地时区都通过 TimeZoneInfo.Local 属性来引用,而从未分配给对象变量。 这是一种建议做法,因为调用 TimeZoneInfo.ClearCachedData 方法会使分配了本地时区的任何对象都失效。
编译代码
此示例需要:
在项目中添加一个对 System.Core.dll 的引用。
使用 using 语句导入 System 命名空间(在 C# 代码中需要)。