操作說明:讓使用者解決模稜兩可的時間

不明確的時間是指對應到多個國際標準時間 (UTC) 的時間。 發生時機是往回調整時鐘時間,例如從時區的日光節約時間轉換到其標準時間期間。 處理不明確的時間時,您可以執行下列其中一項:

  • 如果不明確的時間是使用者所輸入的資料項目,可交由使用者解決此不明確狀況。

  • 假設如何將時間對應至 UTC。 例如,您可以假設不明確的時間一律是以時區的標準時間表示。

本主題示範如何讓使用者解決不明確的時間。

讓使用者解決不明確的時間

  1. 取得使用者的時間和日期輸入。

  2. 呼叫 IsAmbiguousTime 方法來判斷時間是否模棱兩可。

  3. 如果時間模棱兩可,請呼叫 GetAmbiguousTimeOffsets 方法來擷取 TimeSpan 物件的陣列。 陣列中的每個項目都包含一個模棱兩可時間可能對應的 UTC 位移。

  4. 讓使用者選取想要的位移。

  5. 將當地時間減去使用者所選取的位移,以取得 UTC 日期和時間。

  6. 呼叫 static (Visual Basic .NET 中的 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 方法的呼叫會讓任何指派給當地時區的物件失效。

編譯程式碼

這個範例需要:

  • 透過 using 陳述式匯入 System 命名空間 (C# 程式碼中的必要項目)。

另請參閱