Postupy: Umožnění řešení nejednoznačných časových údajů pro uživatele

Nejednoznačný čas je čas, který se mapuje na více než jeden koordinovaný univerzální čas (UTC). Dochází k tomu, když se hodinový čas upraví zpět v čase, například při přechodu z letního času časového pásma na standardní čas. Při zpracování nejednoznačné doby můžete udělat jednu z těchto věcí:

  • Pokud nejednoznačný čas představuje položku dat zadaná uživatelem, můžete ji nechat uživateli, aby přeložil nejednoznačnost.

  • Představte si, jak se čas mapuje na UTC. Můžete například předpokládat, že nejednoznačný čas se vždy vyjadřuje ve standardním čase časového pásma.

Toto téma ukazuje, jak umožnit uživateli vyřešit nejednoznačný čas.

Jak umožnit uživateli vyřešit nejednoznačný čas

  1. Získá zadání data a času uživatelem.

  2. IsAmbiguousTime Voláním metody určete, zda je čas nejednoznačný.

  3. Pokud je čas nejednoznačný, zavolejte metodu GetAmbiguousTimeOffsets pro načtení pole TimeSpan objektů. Každý prvek v poli obsahuje posun UTC, na který lze namapovat nejednoznačný čas.

  4. Nechte uživatele vybrat požadovaný posun.

  5. Získejte datum a čas UTC odečtením posunu vybraného uživatelem z místního času.

  6. static Volání metody (Shared v jazyce Visual Basic .NET) SpecifyKind k nastavení vlastnosti hodnoty Kind data a času UTC na DateTimeKind.Utc.

Příklad

Následující příklad uživatele vyzve k zadání data a času a pokud je nejednoznačný, umožní uživateli vybrat čas UTC, na který se nejednoznačný čas mapuje.

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

Jádro ukázkového kódu používá pole TimeSpan objektů k označení možných posunů nejednoznačného času od UTC. Tyto posuny ale pravděpodobně nebudou pro uživatele smysluplné. Pro objasnění významu posunů si kód také všimněte, zda posun představuje standardní čas místního časového pásma nebo jeho letní čas. Kód určuje, který čas je standardní a který čas je letní, porovnáním posunu s hodnotou BaseUtcOffset vlastnosti. Tato vlastnost označuje rozdíl mezi standardem UTC a standardním časem časového pásma.

V tomto příkladu jsou všechny odkazy na místní časové pásmo provedeny prostřednictvím TimeZoneInfo.Local vlastnosti; místní časové pásmo není nikdy přiřazeno k proměnné objektu. Toto je doporučený postup, protože volání TimeZoneInfo.ClearCachedData metody zneplatňuje všechny objekty, ke kterým je přiřazeno místní časové pásmo.

Zkompilování kódu

Tento příklad vyžaduje:

  • Že se System obor názvů importuje pomocí using příkazu (vyžaduje se v kódu jazyka C#).

Viz také