Anvisningar: Låt användare lösa tvetydiga tider
En tvetydig tid är en tid som mappar till mer än en samordnad universell tid (UTC). Det inträffar när klocktiden justeras tillbaka i tiden, till exempel under övergången från en tidszons sommartid till dess standardtid. När du hanterar en tvetydig tid kan du göra något av följande:
Om den tvetydiga tiden är ett dataobjekt som användaren anger kan du låta användaren lösa tvetydigheten.
Gör ett antagande om hur tiden mappar till UTC. Du kan till exempel anta att en tvetydig tid alltid uttrycks i tidszonens standardtid.
Det här avsnittet visar hur du låter en användare lösa en tvetydig tid.
Så här låter du en användare lösa en tvetydig tid
Hämta datum- och tidsindata från användaren.
IsAmbiguousTime Anropa metoden för att avgöra om tiden är tvetydig.
Om tiden är tvetydig anropar GetAmbiguousTimeOffsets du metoden för att hämta en matris med TimeSpan objekt. Varje element i matrisen innehåller en UTC-förskjutning som den tvetydiga tiden kan mappas till.
Låt användaren välja önskad förskjutning.
Hämta UTC-datum och tid genom att subtrahera den förskjutning som användaren har valt från den lokala tiden.
static
Anropa metoden (Shared
i Visual Basic .NET) SpecifyKind för att ange utc-datum- och tidsvärdets Kind egenskap till DateTimeKind.Utc.
Exempel
I följande exempel uppmanas användaren att ange ett datum och en tid och, om det är tvetydigt, låter användaren välja den UTC-tid som den tvetydiga tiden mappar till.
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
Kärnan i exempelkoden använder en matris med TimeSpan objekt för att ange möjliga förskjutningar av den tvetydiga tiden från UTC. Dessa förskjutningar är dock osannolikt att vara meningsfulla för användaren. För att klargöra innebörden av förskjutningarna noterar koden även om en förskjutning representerar den lokala tidszonens standardtid eller dess sommartid. Koden avgör vilken tid som är standard och vilken tid som är dagsljus genom att jämföra förskjutningen med värdet för BaseUtcOffset egenskapen. Den här egenskapen anger skillnaden mellan UTC och tidszonens standardtid.
I det här exemplet görs alla referenser till den lokala tidszonen TimeZoneInfo.Local via egenskapen. Den lokala tidszonen tilldelas aldrig till en objektvariabel. Detta är en rekommenderad metod eftersom ett anrop till TimeZoneInfo.ClearCachedData metoden ogiltigförklarar alla objekt som den lokala tidszonen har tilldelats till.