方法: ユーザーがあいまいな時刻を解決できるようにする
あいまいな時刻は複数の世界協定時刻 (UTC) にマップされる時刻です。 あいまいな時刻は、あるタイム ゾーンの夏時間から標準時間に移行する際など、時計の時刻を前に戻すときに発生します。 あいまいな時刻を処理する場合は、次のいずれかの操作を行います。
あいまいな時刻が、ユーザーによって入力されたデータ項目である場合は、あいまいさの解決をユーザーに任せることができます。
時刻が UTC にどのようにマップされるかを想定します。 たとえば、あいまいな時刻は常にタイム ゾーンの標準時刻で表されると想定できます。
このトピックでは、ユーザーにあいまいな時刻を解決させる方法を示します。
ユーザーにあいまいな時刻を解決させるには
ユーザーによって入力された日付と時刻を取得します。
時刻があいまいかどうかを確認するには、IsAmbiguousTime メソッドを呼び出します。
時刻があいまいな場合は、GetAmbiguousTimeOffsets メソッドを呼び出して TimeSpan オブジェクトの配列を取得します。 配列の各要素には、あいまいな時刻をマップできる UTC オフセットが含まれています。
ユーザーに目的のオフセットを選択させます。
ローカル時刻からユーザーによって選択されたオフセットを減算して、UTC の日時を取得します。
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 メソッドの呼び出しによって無効にされる可能性があるため、これがお勧めの方法です。
関連項目
.NET