如何:让用户解析不明确的时间
不明确时间是指映射到多个协调世界时 (UTC) 的时间。 在向后调整时钟时间时,例如从时区的夏令时调整到标准时间这段转换期间,便会出现不明确时间。 在处理不明确时间时,可执行以下任一操作:
如果不明确时间是用户输入的数据项,则可以让用户自行解决。
假设一下时间如何映射到 UTC。 例如,可以假定不明确时间始终以时区的标准时间表示。
本主题介绍如何让用户解析不明确时间。
让用户解决不明确时间
获取用户输入的日期和时间。
调用 IsAmbiguousTime 方法来确定时间是否不明确。
如果时间不明确,请调用 GetAmbiguousTimeOffsets 方法来检索 TimeSpan 对象的数组。 数组中的每个元素都包含一个 UTC 时差,不明确时间可以映射到该 UTC 时差。
让用户选择所需时差。
用本地时间减去用户所选时差,得出 UTC 日期和时间。
调用
static
(Visual Basic 中的Shared
)SpecifyKind 方法,将 UTC 日期和时间值的 Kind 属性设置为 DateTimeKind.Utc。
示例
以下示例将提示用户输入日期和时间,如果时间不明确,会让用户选择不明确时间映射到的 UTC 时间。
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($"{ctr}.) {offsets[ctr].Hours} hours, {offsets[ctr].Minutes} 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($"{inputDate} local time corresponds to {utcDate} {utcDate.Kind.ToString()}.");
}
else
{
utcDate = inputDate.ToUniversalTime();
Console.WriteLine($"{inputDate} local time corresponds to {utcDate} {utcDate.Kind.ToString()}.");
}
}
private static DateTime GetUserDateTime()
{
// Flag to exit loop if date is valid.
bool exitFlag = false;
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;
}
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
该示例代码的核心使用一组 TimeSpan 对象,来指示不明确时间与 UTC 之间可能的时差。 但是,这些时差值对用户可能没有什么意义。 为了阐明时差的含义,该代码还会指示时差是表示本地时区的标准时间还是其夏令时。 该代码通过将时差与 BaseUtcOffset 属性的值相比较,确定哪个是标准时间,哪个是夏令时。 此属性指示 UTC 与时区的标准时间之差。
在本示例中,均通过 TimeZoneInfo.Local 属性引用本地时区;绝不会将本地时区分配给对象变量。 这是建议做法,因为调用 TimeZoneInfo.ClearCachedData 方法会使本地时区分配到的任何对象无效。