言語

方法: ラウンドトリップの日付と時刻の値

多くのアプリケーションでは、日付と時刻の値は、1 つの時点を明確に識別することを目的としています。 この記事では、復元された値が保存された値と同じ時刻を識別できるように、 DateTime 値、 DateTimeOffset 値、およびタイム ゾーン情報を含む日付と時刻の値を保存および復元する方法について説明します。

日時値の往復処理

  1. DateTime値を文字列形式に変換するには、"o" 書式指定子を使用して DateTime.ToString(String) メソッドを呼び出します。

  2. DateTime値の文字列形式をファイルに保存するか、プロセス、アプリケーション ドメイン、またはコンピューターの境界を越えて渡します。

  3. DateTime値を表す文字列を取得します。

  4. DateTime.Parse(String, IFormatProvider, DateTimeStyles) メソッドを呼び出し、DateTimeStyles.RoundtripKind パラメーターの値としてstylesを渡します。

次の例は、 DateTime 値をラウンド トリップする方法を示しています。

const string fileName = @".\DateFile.txt";

StreamWriter outFile = new StreamWriter(fileName);

// Save DateTime value.
DateTime dateToSave = DateTime.SpecifyKind(new DateTime(2008, 6, 12, 18, 45, 15),
                                           DateTimeKind.Local);
string? dateString = dateToSave.ToString("o");
Console.WriteLine($"Converted {dateToSave.ToString()} ({dateToSave.Kind.ToString()}) to {dateString}.");
outFile.WriteLine(dateString);
Console.WriteLine($"Wrote {dateString} to {fileName}.");
outFile.Close();

// Restore DateTime value.
DateTime restoredDate;

using StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();

if (dateString is not null)
{
    restoredDate = DateTime.Parse(dateString, null, DateTimeStyles.RoundtripKind);
    Console.WriteLine($"Read {restoredDate.ToString()} ({restoredDate.Kind.ToString()}) from {fileName}.");
}

// The example displays the following output:
//    Converted 6/12/2008 6:45:15 PM (Local) to 2008-06-12T18:45:15.0000000-05:00.
//    Wrote 2008-06-12T18:45:15.0000000-05:00 to .\DateFile.txt.
//    Read 6/12/2008 6:45:15 PM (Local) from .\DateFile.txt.
Const fileName As String = ".\DateFile.txt"

Dim outFile As New StreamWriter(fileName)

' Save DateTime value.
Dim dateToSave As Date = DateTime.SpecifyKind(#06/12/2008 6:45:15 PM#, _
                                              DateTimeKind.Local)
Dim dateString As String = dateToSave.ToString("o")
Console.WriteLine("Converted {0} ({1}) to {2}.", dateToSave.ToString(), _
                  dateToSave.Kind.ToString(), dateString)
outFile.WriteLine(dateString)
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName)
outFile.Close()

' Restore DateTime value.
Dim restoredDate As Date

Dim inFile As New StreamReader(fileName)
dateString = inFile.ReadLine()
inFile.Close()
restoredDate = DateTime.Parse(dateString, Nothing, DateTimeStyles.RoundTripKind)
Console.WriteLine("Read {0} ({2}) from {1}.", restoredDate.ToString(), _
                  fileName, restoredDAte.Kind.ToString())
' The example displays the following output:
'    Converted 6/12/2008 6:45:15 PM (Local) to 2008-06-12T18:45:15.0000000-05:00.
'    Wrote 2008-06-12T18:45:15.0000000-05:00 to .\DateFile.txt.
'    Read 6/12/2008 6:45:15 PM (Local) from .\DateFile.txt.

DateTime値をラウンドトリップする場合、この手法では、すべてのローカル時刻とユニバーサル時刻の時間が正常に保持されます。 たとえば、ローカル DateTime 値が米国太平洋標準時ゾーンのシステムに保存され、米国中部標準タイム ゾーンのシステムで復元される場合、復元された日時は元の時刻より 2 時間遅れになり、2 つのタイム ゾーン間の時間差が反映されます。 ただし、この手法は、指定されていない時間に対して必ずしも正確であるとは限りません。 DateTime プロパティがKindされているすべてのUnspecified値は、ローカル時刻であるかのように扱われます。 ローカル時刻でない場合、 DateTime は正しい時点を正しく識別できません。 この制限の回避策は、日付と時刻の値と、保存および復元操作のタイム ゾーンを厳密に結合することです。

DateTimeOffset 値の往復

  1. DateTimeOffset値を文字列形式に変換するには、"o" 書式指定子を使用して DateTimeOffset.ToString(String) メソッドを呼び出します。

  2. DateTimeOffset値の文字列形式をファイルに保存するか、プロセス、アプリケーション ドメイン、またはコンピューターの境界を越えて渡します。

  3. DateTimeOffset値を表す文字列を取得します。

  4. DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) メソッドを呼び出し、DateTimeStyles.RoundtripKind パラメーターの値としてstylesを渡します。

次の例は、 DateTimeOffset 値をラウンド トリップする方法を示しています。

const string fileName = @".\DateOff.txt";

StreamWriter outFile = new StreamWriter(fileName);

// Save DateTime value.
DateTimeOffset dateToSave = new DateTimeOffset(2008, 6, 12, 18, 45, 15,
                                               new TimeSpan(7, 0, 0));
string? dateString = dateToSave.ToString("o");
Console.WriteLine($"Converted {dateToSave.ToString()} to {dateString}.");
outFile.WriteLine(dateString);
Console.WriteLine($"Wrote {dateString} to {fileName}.");
outFile.Close();

// Restore DateTime value.
DateTimeOffset restoredDateOff;

using StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();

if (dateString is not null)
{
    restoredDateOff = DateTimeOffset.Parse(dateString, null,
                                           DateTimeStyles.RoundtripKind);
    Console.WriteLine($"Read {restoredDateOff.ToString()} from {fileName}.");
}

// The example displays the following output:
//    Converted 6/12/2008 6:45:15 PM +07:00 to 2008-06-12T18:45:15.0000000+07:00.
//    Wrote 2008-06-12T18:45:15.0000000+07:00 to .\DateOff.txt.
//    Read 6/12/2008 6:45:15 PM +07:00 from .\DateOff.txt.
Const fileName As String = ".\DateOff.txt"

Dim outFile As New StreamWriter(fileName)

' Save DateTime value.
Dim dateToSave As New DateTimeOffset(2008, 6, 12, 18, 45, 15, _
                                     New TimeSpan(7, 0, 0))
Dim dateString As String = dateToSave.ToString("o")
Console.WriteLine("Converted {0} to {1}.", dateToSave.ToString(), dateString)
outFile.WriteLine(dateString)
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName)
outFile.Close()

' Restore DateTime value.
Dim restoredDateOff As DateTimeOffset

Dim inFile As New StreamReader(fileName)
dateString = inFile.ReadLine()
inFile.Close()
restoredDateOff = DateTimeOffset.Parse(dateString, Nothing, DateTimeStyles.RoundTripKind)
Console.WriteLine("Read {0} from {1}.", restoredDateOff.ToString(), fileName)
' The example displays the following output:
'    Converted 6/12/2008 6:45:15 PM +07:00 to 2008-06-12T18:45:15.0000000+07:00.
'    Wrote 2008-06-12T18:45:15.0000000+07:00 to .\DateOff.txt.
'    Read 6/12/2008 6:45:15 PM +07:00 from .\DateOff.txt.

この手法では、常に DateTimeOffset 値が 1 つの時点として明確に識別されます。 その後、 DateTimeOffset.ToUniversalTime メソッドを呼び出して世界協定時刻 (UTC) に変換するか、 DateTimeOffset.ToOffset または TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) メソッドを呼び出して特定のタイム ゾーンの時刻に変換できます。 この手法の主な制限は、日付と時刻の算術演算が、特定のタイム ゾーンの時刻を表す DateTimeOffset 値に対して実行されると、そのタイム ゾーンの正確な結果が得られない可能性があるということです。 これは、 DateTimeOffset 値がインスタンス化されると、タイム ゾーンとの関連付けが解除されるためです。 そのため、日付と時刻の計算を実行するときに、そのタイム ゾーンの調整規則を適用できなくなります。 この問題を回避するには、日付と時刻の値とそれに付随するタイム ゾーンの両方を含むカスタム型を定義します。

コードをコンパイルする

これらの例では、C# using ディレクティブまたは Visual Basic Imports ステートメントを使用して、次の名前空間をインポートする必要があります。

こちらも参照ください