Instrukcje: Pozwalanie użytkownikom na rozwiązywanie niejednoznacznych wartości czasu

Niejednoznaczny czas to czas, który mapuje na więcej niż jeden uniwersalny czas koordynowany (UTC). Występuje, gdy czas zegara jest dostosowywany z powrotem w czasie, na przykład podczas przejścia ze strefy czasowej czas letni do czasu standardowego. W przypadku obsługi niejednoznacznego czasu można wykonać jedną z następujących czynności:

  • Jeśli niejednoznaczny czas jest elementem danych wprowadzonym przez użytkownika, możesz pozostawić go użytkownikowi, aby rozwiązać niejednoznaczność.

  • Przyjmij założenie dotyczące sposobu mapowania czasu na czas UTC. Można na przykład założyć, że niejednoznaczny czas jest zawsze wyrażony w standardowym czasie strefy czasowej.

W tym temacie pokazano, jak umożliwić użytkownikowi rozwiązanie niejednoznacznego czasu.

Aby umożliwić użytkownikowi rozwiązanie niejednoznacznego czasu

  1. Pobierz dane wejściowe daty i godziny przez użytkownika.

  2. Wywołaj metodę , IsAmbiguousTime aby określić, czy czas jest niejednoznaczny.

  3. Jeśli czas jest niejednoznaczny, wywołaj metodę GetAmbiguousTimeOffsets , aby pobrać tablicę TimeSpan obiektów. Każdy element tablicy zawiera przesunięcie UTC, na które może być mapowany niejednoznaczny czas.

  4. Pozwól użytkownikowi wybrać żądane przesunięcie.

  5. Pobierz datę i godzinę UTC, odejmując przesunięcie wybrane przez użytkownika z czasu lokalnego.

  6. Wywołaj metodę static (Shared w języku Visual Basic .NET), SpecifyKind aby ustawić właściwość wartości Kind daty i godziny UTC na DateTimeKind.Utcwartość .

Przykład

Poniższy przykład monituje użytkownika o wprowadzenie daty i godziny, a jeśli jest niejednoznaczny, pozwala użytkownikowi wybrać godzinę UTC, do której mapuje się niejednoznaczny czas.

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

Rdzeń przykładowego kodu używa tablicy TimeSpan obiektów, aby wskazać możliwe przesunięcia niejednoznacznego czasu od UTC. Jednak te przesunięcia są mało prawdopodobne, aby były istotne dla użytkownika. Aby wyjaśnić znaczenie przesunięć, kod zauważa również, czy przesunięcie reprezentuje standardowy czas lokalnej strefy czasowej, czy czas letni. Kod określa, który czas jest standardowy i jaki czas jest letni, porównując przesunięcie z wartością BaseUtcOffset właściwości. Ta właściwość wskazuje różnicę między czasem UTC a czasem standardowym strefy czasowej.

W tym przykładzie wszystkie odwołania do lokalnej strefy czasowej są wykonywane za pośrednictwem TimeZoneInfo.Local właściwości ; lokalna strefa czasowa nigdy nie jest przypisana do zmiennej obiektu. Jest to zalecana praktyka, ponieważ wywołanie TimeZoneInfo.ClearCachedData metody unieważnia wszystkie obiekty, do których przypisano lokalną strefę czasową.

Kompilowanie kodu

Ten przykład wymaga:

  • System Czy przestrzeń nazw zostanie zaimportowana z instrukcją using (wymaganą w kodzie języka C#).

Zobacz też