System.DateTime 構造体

この記事は、この API のリファレンス ドキュメントの補足説明です。

重要

和暦の時代 (年号) は天皇の代に基づいているため、変更されることが予想されます。 たとえば、JapaneseCalendarJapaneseLunisolarCalendar において、2019 年 5 月 1 日から令和時代が始まることになりました。 このような時代 (年号) の変更は、これらのカレンダーを使用するすべてのアプリケーションに影響します。 詳細およびアプリケーションが影響を受けるかどうかを判断するには、「.NET の日本語カレンダーでの新しい時代 (年号) の処理」を参照してください。 Windows システムでアプリケーションをテストし、時代 (年号) の変更に対する準備を行う方法については、「日本の時代 (年号) に合わせてアプリケーションを準備する」を参照してください。 複数の時代 (年号) を含むカレンダーをサポートする .NET の機能と、複数の時代 (年号) をサポートするカレンダーを使用する場合のベスト プラクティスについては、「年号の使用」を参照してください

概要

値の型は DateTime 、グレゴリオ暦の 9999 年 12 月 31 日午後 11 時 59 分 59 分 59 秒まで、00:00:00 (午前 0 時)、0001 年 1 月 1 日アンノ ドミニ (共通時代) までの値を持つ日付と時刻を表します。

時間値は、ティックと呼ばれる 100 ナノ秒単位で測定されます。 特定の日付は、カレンダーの 0001 年 GregorianCalendar 1 月 1 日午前 12 時 00 分からのティック数です。 この数値は、閏秒で加算されるティックを除外します。 たとえば、ティック値 31241376000000000L は、0100 年 1 月 1 日 12:00:00 の午前 0 時の日付を表します。 DateTime値は、常に明示的または既定の予定表のコンテキストで表されます。

Note

分や秒など、他の時間間隔に変換するティック値を使用する場合は、変換をTimeSpan.TicksPerDay実行するために 、TimeSpan.TicksPerHour、、TimeSpan.TicksPerMinuteTimeSpan.TicksPerSecond、またはTimeSpan.TicksPerMillisecond定数を使用する必要があります。 たとえば、指定したティック数で表される秒数を値のDateTimeコンポーネントにSecond追加するには、式dateValue.Second + nTicks/Timespan.TicksPerSecondを使用します。

この記事の一連の例全体のソースは、Visual Basic、F#または C# で確認できます。

Note

特定のタイム ゾーンで日付と時刻の DateTime 値を操作するための構造の代わりに、構造体があります DateTimeOffset 。 構造体は DateTimeOffset 、日付と時刻の情報をプライベート DateTime フィールドに格納し、その日付と時刻がプライベート Int16 フィールドの UTC と異なる分数を格納します。 これにより、値に特定の DateTimeOffset タイム ゾーンの時刻を反映させることができますが DateTime 、値は UTC とローカル タイム ゾーンの時刻のみを明確に反映できます。 日付と時刻の値を操作するときに構造体またはDateTimeOffset構造体を使用DateTimeするタイミングについては、「DateTime、DateTimeOffset、TimeSpan、TimeZoneInfo の選択」を参照してください

Note

この記事にある C# の例の一部は、Try.NET インライン コード ランナーとプレイグラウンドで実行されます。 [実行] ボタンを選択すると、対話型ウィンドウで例が実行されます。 コードを実行したら、コードを変更し、 [実行] をもう一度選択して変更後のコードを実行できます。 変更後のコードが対話型ウィンドウで実行されるか、コンパイルできなかった場合、対話型ウィンドウにすべての C# コンパイラ エラー メッセージが表示されます。

Try.NET インライン コード ランナーとプレイグラウンドのローカル タイム ゾーンは、協定世界時 (UTC) です。 これは、DateTimeDateTimeOffsetTimeZoneInfo 型とそのメンバーについて説明する例の、動作と出力に影響を与える可能性があります。

この記事には、この型を使用するいくつかの例が DateTime 含まれています。

初期化の例

オブジェクトを文字列の例として書式設定 DateTime する

オブジェクトとしての DateTime 文字列の解析の例

DateTime 解決策の例

カルチャとカレンダーの例

永続化の例

DateTime オブジェクトを初期化する

初期値は、さまざまな方法で新しい DateTime 値に割り当てることができます。

  • コンストラクターを呼び出します。値の引数を指定するか、暗黙的なパラメーターなしのコンストラクターを使用します。
  • DateTimeプロパティまたはメソッドの戻り値に a を割り当てる。
  • DateTime文字列表現からの値の解析。
  • Visual Basic 固有の言語機能を使用してインスタンス化します DateTime

次のコード スニペットは、それぞれの例を示しています。

コンストラクターを呼び出す

日付と時刻の DateTime 値 (年、月、日、ティック数など) の要素を指定するコンストラクターのオーバーロードのいずれかを呼び出します。 次のコードでは、年、月、日、時、分、秒を指定するコンストラクターを使用して DateTime 、特定の日付を作成します。

Dim date1 As New Date(2008, 5, 1, 8, 30, 52)
var date1 = new DateTime(2008, 5, 1, 8, 30, 52);
Console.WriteLine(date1);
let date1 = DateTime(2008, 5, 1, 8, 30, 52)
printfn $"{date1}"

既定値に初期化する DateTime 場合は、構造体の暗黙的な DateTime パラメーターなしのコンストラクターを呼び出します。 (値型の暗黙的なパラメーターなしのコンストラクターの詳細については、 値の型。)一部のコンパイラでは、値を DateTime 明示的に割り当てずに値を宣言することもできます。 明示的な初期化なしで値を作成すると、既定値にもなります。 次の例は、 DateTime C# と Visual Basic の暗黙的なパラメーターなしのコンストラクターと、 DateTime Visual Basic での割り当てなしの宣言を示しています。

Dim dat1 As DateTime
' The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat1.ToString(System.Globalization.CultureInfo.InvariantCulture))
' The following method call displays True.
Console.WriteLine(dat1.Equals(Date.MinValue))

Dim dat2 As New DateTime()
' The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat2.ToString(System.Globalization.CultureInfo.InvariantCulture))
' The following method call displays True.
Console.WriteLine(dat2.Equals(Date.MinValue))
var dat1 = new DateTime();
// The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat1.ToString(System.Globalization.CultureInfo.InvariantCulture));
// The following method call displays True.
Console.WriteLine(dat1.Equals(DateTime.MinValue));
let dat1 = DateTime()

// The following method call displays 1/1/0001 12:00:00 AM.
printfn $"{dat1.ToString System.Globalization.CultureInfo.InvariantCulture}"

// The following method call displays True.
printfn $"{dat1.Equals DateTime.MinValue}"

計算値を割り当てる

オブジェクトには DateTime 、プロパティまたはメソッドによって返される日付と時刻の値を割り当てることができます。 次の例では、現在の日付と時刻、現在の世界協定時刻 (UTC) の日付と時刻、および現在の日付を 3 つの新しい DateTime 変数に割り当てます。

Dim date1 As Date = Date.Now
Dim date2 As Date = Date.UtcNow
Dim date3 As Date = Date.Today
DateTime date1 = DateTime.Now;
DateTime date2 = DateTime.UtcNow;
DateTime date3 = DateTime.Today;
let date1 = DateTime.Now
let date2 = DateTime.UtcNow
let date3 = DateTime.Today

DateTime を表す文字列を解析する

ParseExactTryParseおよびTryParseExactメソッドはすべてParse、文字列を等価の日付と時刻の値に変換します。 次の例では、and メソッドをParse使用して文字列を解析し、それを値にDateTime変換ParseExactします。 2 番目の形式では、文字列形式で日付と時刻を 表す ISO 8601 標準でサポートされているフォームを使用します。 この標準表現は、多くの場合、Web サービスの日付情報を転送するために使用されます。

Dim dateString As String = "5/1/2008 8:30:52 AM"
Dim date1 As Date = Date.Parse(dateString,
                       System.Globalization.CultureInfo.InvariantCulture)
Dim iso8601String As String = "20080501T08:30:52Z"
Dim dateISO8602 As Date = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
                              System.Globalization.CultureInfo.InvariantCulture)
Console.WriteLine(dateISO8602)
var dateString = "5/1/2008 8:30:52 AM";
DateTime date1 = DateTime.Parse(dateString,
                          System.Globalization.CultureInfo.InvariantCulture);
var iso8601String = "20080501T08:30:52Z";
DateTime dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
                                System.Globalization.CultureInfo.InvariantCulture);
let dateString = "5/1/2008 8:30:52 AM"
let date1 = DateTime.Parse(dateString, System.Globalization.CultureInfo.InvariantCulture)
let iso8601String = "20080501T08:30:52Z"
let dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ", System.Globalization.CultureInfo.InvariantCulture)

and TryParseExact メソッドはTryParse、文字列が値のDateTime有効な表現であるかどうかを示し、有効な場合は変換を実行します。

Visual Basic の言語固有の構文

次の Visual Basic ステートメントは、新しい DateTime 値を初期化します。

Dim date1 As Date = #5/1/2008 8:30:52AM#

DateTime 値とその文字列表現

内部的には、すべての DateTime 値は、0001 年 1 月 1 日午前 12 時 00 分 00 分から経過したティック数 (100 ナノ秒間隔の数) として表されます。 実際 DateTime の値は、表示時にその値が表示される方法とは無関係です。 値の外観は、 DateTime 値を文字列形式に変換する書式設定操作の結果です。

日付と時刻の値の外観は、カルチャ、国際標準、アプリケーション要件、個人の好みに応じて異なります。 構造体は DateTime 、のオーバーロードを使用して日付と時刻の ToString値を書式設定する柔軟性を提供します。 既定 DateTime.ToString() のメソッドは、現在のカルチャの短い日付と長い時間パターンを使用して、日付と時刻の値の文字列形式を返します。 次の例では、既定のメソッドを使用します DateTime.ToString() 。 現在のカルチャの短い日付と長い時間パターンを使用して、日付と時刻が表示されます。 en-US カルチャは、例が実行されたコンピューター上の現在のカルチャです。

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString());
// For en-US culture, displays 3/1/2008 7:00:00 AM
let date1 = DateTime(2008, 3, 1, 7, 0, 0)
printfn $"{date1.ToString()}"
// For en-US culture, displays 3/1/2008 7:00:00 AM
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString())
' For en-US culture, displays 3/1/2008 7:00:00 AM

サーバーがクライアントとは異なるカルチャにある可能性がある Web シナリオをサポートするために、特定のカルチャの日付の書式設定が必要になる場合があります。 特定のカルチャで短い日付と長い時間の表現を作成するには、メソッドを使用して DateTime.ToString(IFormatProvider) カルチャを指定します。 次の例では、 DateTime.ToString(IFormatProvider) fr-FR カルチャの短い日付と長い時刻パターンを使用して、メソッドを使用して日付と時刻を表示します。

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")));
// Displays 01/03/2008 07:00:00
let date1 = DateTime(2008, 3, 1, 7, 0, 0)
printfn $"""{date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture "fr-FR")}"""
// Displays 01/03/2008 07:00:00
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")))
' Displays 01/03/2008 07:00:00

他のアプリケーションでは、日付の異なる文字列表現が必要になる場合があります。 このメソッドは DateTime.ToString(String) 、現在のカルチャの書式設定規則を使用して、標準書式指定子またはカスタム書式指定子によって定義された文字列形式を返します。 次の例では、このメソッドを DateTime.ToString(String) 使用して、en-US カルチャの完全な日付と時刻のパターン、例が実行されたコンピューター上の現在のカルチャを表示します。

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("F"));
// Displays Saturday, March 01, 2008 7:00:00 AM
let date1 = DateTime(2008, 3, 1, 7, 0, 0)
printfn $"""{date1.ToString "F"}"""
// Displays Saturday, March 01, 2008 7:00:00 AM
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString("F"))
' Displays Saturday, March 01, 2008 7:00:00 AM

最後に、メソッドを使用してカルチャと形式の両方を DateTime.ToString(String, IFormatProvider) 指定できます。 次の例では、このメソッドを DateTime.ToString(String, IFormatProvider) 使用して、fr-FR カルチャの完全な日付と時刻のパターンを表示します。

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("F", new System.Globalization.CultureInfo("fr-FR")));
// Displays samedi 1 mars 2008 07:00:00
let date1 = DateTime(2008, 3, 1, 7, 0, 0)
printfn $"""{date1.ToString("F", new System.Globalization.CultureInfo "fr-FR")}"""
// Displays samedi 1 mars 2008 07:00:00
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString("F", New System.Globalization.CultureInfo("fr-FR")))
' Displays samedi 1 mars 2008 07:00:00

オーバーロードは DateTime.ToString(String) 、カスタム書式指定文字列と共に使用して、他の形式を指定することもできます。 次の例は、Web サービスでよく使用される ISO 8601 標準形式を使用して文字列を書式設定する方法を示しています。 Iso 8601 形式には、対応する標準書式指定文字列がありません。

var date1 = new DateTime(2008, 3, 1, 7, 0, 0, DateTimeKind.Utc);
Console.WriteLine(date1.ToString("yyyy-MM-ddTHH:mm:sszzz", System.Globalization.CultureInfo.InvariantCulture));
// Displays 2008-03-01T07:00:00+00:00
let date1 = DateTime(2008, 3, 1, 7, 0, 0, DateTimeKind.Utc)
printfn $"""{date1.ToString("yyyy-MM-ddTHH:mm:sszzz", System.Globalization.CultureInfo.InvariantCulture)}"""
// Displays 2008-03-01T07:00:00+00:00
Dim date1 As DateTime = New DateTime(2008, 3, 1, 7, 0, 0, DateTimeKind.Utc)
Console.WriteLine(date1.ToString("yyyy-MM-ddTHH:mm:sszzz", System.Globalization.CultureInfo.InvariantCulture))
' Displays 2008-03-01T07:00:00+00:00

値のDateTime書式設定の詳細については、「標準の日付と時刻の書式指定文字列」および「カスタム日時書式指定文字列」を参照してください。

文字列から DateTime 値を解析する

解析では、日付と時刻の文字列形式を値に DateTime 変換します。 通常、日付と時刻の文字列には、アプリケーションで次の 2 つの使用法があります。

  • 日付と時刻にはさまざまな形式があり、現在のカルチャまたは特定のカルチャの規則が反映されます。 たとえば、アプリケーションを使用すると、現在のカルチャが en-US であるユーザーは、日付値を "2013 年 12 月 15 日" または "2013 年 12 月 15 日" として入力できます。 現在のカルチャが en-gb のユーザーは、日付値を "15/12/2013" または "2013 年 12 月 15 日" として入力できます。

  • 日付と時刻は、定義済みの形式で表されます。 たとえば、アプリケーションは、アプリが実行されているカルチャとは別に、日付を "20130103" としてシリアル化します。 アプリケーションでは、日付を現在のカルチャの短い日付形式で入力する必要がある場合があります。

or TryParse メソッドをParse使用して、カルチャで使用される一般的な日付と時刻のいずれかの形式から値に文字列をDateTime変換します。 次の例は、カルチャ固有のさまざまな形式の日付文字列を値に変換する方法 TryParseDateTime 示しています。 現在のカルチャを英語 (英国) に変更し、メソッドを GetDateTimeFormats() 呼び出して日付と時刻の文字列の配列を生成します。 次に、配列内の各要素をメソッドに TryParse 渡します。 この例の出力は、解析メソッドがカルチャ固有の各日付と時刻の文字列を正常に変換できたことを示しています。

System.Threading.Thread.CurrentThread.CurrentCulture =
    System.Globalization.CultureInfo.CreateSpecificCulture("en-GB");

var date1 = new DateTime(2013, 6, 1, 12, 32, 30);
var badFormats = new List<String>();

Console.WriteLine($"{"Date String",-37} {"Date",-19}\n");
foreach (var dateString in date1.GetDateTimeFormats())
{
    DateTime parsedDate;
    if (DateTime.TryParse(dateString, out parsedDate))
        Console.WriteLine($"{dateString,-37} {DateTime.Parse(dateString),-19}");
    else
        badFormats.Add(dateString);
}

// Display strings that could not be parsed.
if (badFormats.Count > 0)
{
    Console.WriteLine("\nStrings that could not be parsed: ");
    foreach (var badFormat in badFormats)
        Console.WriteLine($"   {badFormat}");
}
// Press "Run" to see the output.
System.Threading.Thread.CurrentThread.CurrentCulture <-
    System.Globalization.CultureInfo.CreateSpecificCulture "en-GB"

let date1 = DateTime(2013, 6, 1, 12, 32, 30)
let badFormats = ResizeArray<String>()

printfn "%-37s %-19s\n" "Date String" "Date"
for dateString in date1.GetDateTimeFormats() do
    match DateTime.TryParse dateString with
    | true, parsedDate ->
        printfn $"%-37s{dateString} %-19O{parsedDate}\n" 
    | _ ->
        badFormats.Add dateString

// Display strings that could not be parsed.
if badFormats.Count > 0 then
    printfn "\nStrings that could not be parsed: "
    for badFormat in badFormats do
        printfn $"   {badFormat}"
// Press "Run" to see the output.
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB")

Dim date1 As New DateTime(2013, 6, 1, 12, 32, 30)
Dim badFormats As New List(Of String)

Console.WriteLine($"{"Date String",-37} {"Date",-19}")
Console.WriteLine()
For Each dateString As String In date1.GetDateTimeFormats()
    Dim parsedDate As DateTime
    If DateTime.TryParse(dateString, parsedDate) Then
        Console.WriteLine($"{dateString,-37} {DateTime.Parse(dateString),-19:g}")
    Else
        badFormats.Add(dateString)
    End If
Next

' Display strings that could not be parsed.
If badFormats.Count > 0 Then
    Console.WriteLine()
    Console.WriteLine("Strings that could not be parsed: ")
    For Each badFormat In badFormats
        Console.WriteLine($"   {badFormat}")
    Next
End If
' The example displays the following output:
'       Date String                           Date               
'       
'       01/06/2013                            01/06/2013 00:00:00
'       01/06/13                              01/06/2013 00:00:00
'       1/6/13                                01/06/2013 00:00:00
'       1.6.13                                01/06/2013 00:00:00
'       2013-06-01                            01/06/2013 00:00:00
'       01 June 2013                          01/06/2013 00:00:00
'       1 June 2013                           01/06/2013 00:00:00
'       01 June 2013 12:32                    01/06/2013 12:32:00
'       01 June 2013 12:32                    01/06/2013 12:32:00
'       01 June 2013 12:32 PM                 01/06/2013 12:32:00
'       01 June 2013 12:32 PM                 01/06/2013 12:32:00
'       1 June 2013 12:32                     01/06/2013 12:32:00
'       1 June 2013 12:32                     01/06/2013 12:32:00
'       1 June 2013 12:32 PM                  01/06/2013 12:32:00
'       1 June 2013 12:32 PM                  01/06/2013 12:32:00
'       01 June 2013 12:32:30                 01/06/2013 12:32:30
'       01 June 2013 12:32:30                 01/06/2013 12:32:30
'       01 June 2013 12:32:30 PM              01/06/2013 12:32:30
'       01 June 2013 12:32:30 PM              01/06/2013 12:32:30
'       1 June 2013 12:32:30                  01/06/2013 12:32:30
'       1 June 2013 12:32:30                  01/06/2013 12:32:30
'       1 June 2013 12:32:30 PM               01/06/2013 12:32:30
'       1 June 2013 12:32:30 PM               01/06/2013 12:32:30
'       01/06/2013 12:32                      01/06/2013 12:32:00
'       01/06/2013 12:32                      01/06/2013 12:32:00
'       01/06/2013 12:32 PM                   01/06/2013 12:32:00
'       01/06/2013 12:32 PM                   01/06/2013 12:32:00
'       01/06/13 12:32                        01/06/2013 12:32:00
'       01/06/13 12:32                        01/06/2013 12:32:00
'       01/06/13 12:32 PM                     01/06/2013 12:32:00
'       01/06/13 12:32 PM                     01/06/2013 12:32:00
'       1/6/13 12:32                          01/06/2013 12:32:00
'       1/6/13 12:32                          01/06/2013 12:32:00
'       1/6/13 12:32 PM                       01/06/2013 12:32:00
'       1/6/13 12:32 PM                       01/06/2013 12:32:00
'       1.6.13 12:32                          01/06/2013 12:32:00
'       1.6.13 12:32                          01/06/2013 12:32:00
'       1.6.13 12:32 PM                       01/06/2013 12:32:00
'       1.6.13 12:32 PM                       01/06/2013 12:32:00
'       2013-06-01 12:32                      01/06/2013 12:32:00
'       2013-06-01 12:32                      01/06/2013 12:32:00
'       2013-06-01 12:32 PM                   01/06/2013 12:32:00
'       2013-06-01 12:32 PM                   01/06/2013 12:32:00
'       01/06/2013 12:32:30                   01/06/2013 12:32:30
'       01/06/2013 12:32:30                   01/06/2013 12:32:30
'       01/06/2013 12:32:30 PM                01/06/2013 12:32:30
'       01/06/2013 12:32:30 PM                01/06/2013 12:32:30
'       01/06/13 12:32:30                     01/06/2013 12:32:30
'       01/06/13 12:32:30                     01/06/2013 12:32:30
'       01/06/13 12:32:30 PM                  01/06/2013 12:32:30
'       01/06/13 12:32:30 PM                  01/06/2013 12:32:30
'       1/6/13 12:32:30                       01/06/2013 12:32:30
'       1/6/13 12:32:30                       01/06/2013 12:32:30
'       1/6/13 12:32:30 PM                    01/06/2013 12:32:30
'       1/6/13 12:32:30 PM                    01/06/2013 12:32:30
'       1.6.13 12:32:30                       01/06/2013 12:32:30
'       1.6.13 12:32:30                       01/06/2013 12:32:30
'       1.6.13 12:32:30 PM                    01/06/2013 12:32:30
'       1.6.13 12:32:30 PM                    01/06/2013 12:32:30
'       2013-06-01 12:32:30                   01/06/2013 12:32:30
'       2013-06-01 12:32:30                   01/06/2013 12:32:30
'       2013-06-01 12:32:30 PM                01/06/2013 12:32:30
'       2013-06-01 12:32:30 PM                01/06/2013 12:32:30
'       01 June                               01/06/2013 00:00:00
'       01 June                               01/06/2013 00:00:00
'       2013-06-01T12:32:30.0000000           01/06/2013 12:32:30
'       2013-06-01T12:32:30.0000000           01/06/2013 12:32:30
'       Sat, 01 Jun 2013 12:32:30 GMT         01/06/2013 05:32:30
'       Sat, 01 Jun 2013 12:32:30 GMT         01/06/2013 05:32:30
'       2013-06-01T12:32:30                   01/06/2013 12:32:30
'       12:32                                 22/04/2013 12:32:00
'       12:32                                 22/04/2013 12:32:00
'       12:32 PM                              22/04/2013 12:32:00
'       12:32 PM                              22/04/2013 12:32:00
'       12:32:30                              22/04/2013 12:32:30
'       12:32:30                              22/04/2013 12:32:30
'       12:32:30 PM                           22/04/2013 12:32:30
'       12:32:30 PM                           22/04/2013 12:32:30
'       2013-06-01 12:32:30Z                  01/06/2013 05:32:30
'       01 June 2013 19:32:30                 01/06/2013 19:32:30
'       01 June 2013 19:32:30                 01/06/2013 19:32:30
'       01 June 2013 07:32:30 PM              01/06/2013 19:32:30
'       01 June 2013 7:32:30 PM               01/06/2013 19:32:30
'       1 June 2013 19:32:30                  01/06/2013 19:32:30
'       1 June 2013 19:32:30                  01/06/2013 19:32:30
'       1 June 2013 07:32:30 PM               01/06/2013 19:32:30
'       1 June 2013 7:32:30 PM                01/06/2013 19:32:30
'       June 2013                             01/06/2013 00:00:00
'       June 2013                             01/06/2013 00:00:00

and TryParseExact メソッドをParseExact使用して、特定の形式または書式に一致する必要がある文字列を値にDateTime変換します。 解析メソッドのパラメーターとして、1 つ以上の日付と時刻の書式指定文字列を指定します。 次の例では、メソッドを TryParseExact(String, String[], IFormatProvider, DateTimeStyles, DateTime) 使用して、"yyyyMMdd" 形式または "HHmmss" 形式の文字列を値に DateTime 変換します。

string[] formats = { "yyyyMMdd", "HHmmss" };
string[] dateStrings = { "20130816", "20131608", "  20130816   ",
                   "115216", "521116", "  115216  " };
DateTime parsedDate;

foreach (var dateString in dateStrings)
{
    if (DateTime.TryParseExact(dateString, formats, null,
                               System.Globalization.DateTimeStyles.AllowWhiteSpaces |
                               System.Globalization.DateTimeStyles.AdjustToUniversal,
                               out parsedDate))
        Console.WriteLine($"{dateString} --> {parsedDate:g}");
    else
        Console.WriteLine($"Cannot convert {dateString}");
}
// The example displays the following output:
//       20130816 --> 8/16/2013 12:00 AM
//       Cannot convert 20131608
//         20130816    --> 8/16/2013 12:00 AM
//       115216 --> 4/22/2013 11:52 AM
//       Cannot convert 521116
//         115216   --> 4/22/2013 11:52 AM
let formats = [| "yyyyMMdd"; "HHmmss" |]
let dateStrings = 
    [ "20130816"; "20131608"; "  20130816   "
      "115216"; "521116"; "  115216  " ]

for dateString in dateStrings do
    match DateTime.TryParseExact(dateString, formats, null,
                                System.Globalization.DateTimeStyles.AllowWhiteSpaces |||
                                System.Globalization.DateTimeStyles.AdjustToUniversal) with
    | true, parsedDate ->
        printfn $"{dateString} --> {parsedDate:g}"
    | _ ->
        printfn $"Cannot convert {dateString}"

// The example displays the following output:
//       20130816 --> 8/16/2013 12:00 AM
//       Cannot convert 20131608
//         20130816    --> 8/16/2013 12:00 AM
//       115216 --> 4/22/2013 11:52 AM
//       Cannot convert 521116
//         115216   --> 4/22/2013 11:52 AM
Dim formats() As String = {"yyyyMMdd", "HHmmss"}
Dim dateStrings() As String = {"20130816", "20131608",
                              "  20130816   ", "115216",
                              "521116", "  115216  "}
Dim parsedDate As DateTime

For Each dateString As String In dateStrings
    If DateTime.TryParseExact(dateString, formats, Nothing,
                           DateTimeStyles.AllowWhiteSpaces Or
                           DateTimeStyles.AdjustToUniversal,
                           parsedDate) Then
        Console.WriteLine($"{dateString} --> {parsedDate:g}")
    Else
        Console.WriteLine($"Cannot convert {dateString}")
    End If
Next
' The example displays the following output:
'       20130816 --> 8/16/2013 12:00 AM
'       Cannot convert 20131608
'         20130816    --> 8/16/2013 12:00 AM
'       115216 --> 4/22/2013 11:52 AM
'       Cannot convert 521116
'         115216   --> 4/22/2013 11:52 AM

一般的な用途の ParseExact 1 つは、Web サービス (通常は ISO 8601 標準形式) から文字列表現を変換することです。 次のコードは、使用する正しい書式指定文字列を示しています。

var iso8601String = "20080501T08:30:52Z";
DateTime dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
    System.Globalization.CultureInfo.InvariantCulture);
Console.WriteLine($"{iso8601String} --> {dateISO8602:g}");
let iso8601String = "20080501T08:30:52Z"
let dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ", System.Globalization.CultureInfo.InvariantCulture)

printfn $"{iso8601String} --> {dateISO8602:g}"
Dim iso8601String As String = "20080501T08:30:52Z"
Dim dateISO8602 As DateTime = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ", CultureInfo.InvariantCulture)
Console.WriteLine($"{iso8601String} --> {dateISO8602:g}")

文字列を解析できない場合、 Parse メソッドは ParseExact 例外をスローします。 and メソッドはTryParse、変換がBoolean成功したか失敗したかを示す値を返TryParseExactします。 パフォーマンスが TryParse 重要なシナリオでは、または TryParseExact メソッドを使用する必要があります。 日付と時刻の文字列の解析操作は、エラー率が高くなる傾向があり、例外処理はコストがかかります。 文字列がユーザーによって入力された場合、または不明なソースから取得された場合は、これらのメソッドを使用します。

日付と時刻の値の解析の詳細については、「日付と時刻の文字列の解析」を参照してください

DateTime 値

型の DateTime 時刻値の説明は、多くの場合、協定世界時 (UTC) 標準を使用して表されます。 協定世界時はグリニッジ標準時 (GMT) の国際的に認められた名前です。 協定世界時は、経度 0 度 (UTC の起点) で測定された時刻です。 夏時間は UTC には適用されません。

ローカル時刻は、特定のタイム ゾーンを基準としています。 タイム ゾーンはタイム ゾーン オフセットに関連付けられます。 タイム ゾーン オフセットは、UTC の起点から時間単位で測定されたタイム ゾーンの変位です。 さらに、ローカル時刻は必要に応じて夏時間の影響を受け、時間間隔の調整を加算または減算します。 現地時刻は、UTC にタイム ゾーン オフセットを追加し、必要に応じて夏時間に合わせて調整することによって計算されます。 UTC 起点のタイム ゾーン オフセットは 0 です。

UTC 時刻は、計算、比較、および日付と時刻のファイルへの格納に適しています。 ローカル時刻は、デスクトップ アプリケーションのユーザー インターフェイスでの表示に適しています。 タイム ゾーン対応アプリケーション (多くの Web アプリケーションなど) も、他の多くのタイム ゾーンで動作する必要があります。

オブジェクトのKindDateTimeプロパティが指定されている場合、DateTimeKind.Unspecified表される時刻がローカル時刻、UTC 時刻、またはその他のタイム ゾーンの時刻のいずれであるかは指定されません。

DateTime の解決

Note

経過時間を測定するために値に対して日付と時刻の DateTime 算術演算を実行する代わりに、クラスを Stopwatch 使用できます。

このプロパティは Ticks 、日付と時刻の値を 1000 万分の 1 秒の単位で表します。 このプロパティは Millisecond 、日付と時刻の値で秒の 1000 分の 1 を返します。 経過時間を測定するためにプロパティの呼び出しを DateTime.Now 繰り返し使用することは、システム クロックに依存します。 Windows 7 および Windows 8 システムのシステム クロックの解像度は約 15 ミリ秒です。 この解像度は、100 ミリ秒未満の短い時間間隔に影響します。

次の例は、現在の日付と時刻の値がシステム クロックの解像度に依存する方法を示しています。 この例では、外側のループは 20 回繰り返され、内部ループは外側のループを遅延させる役割を果たします。 外側のループ カウンターの値が 10 の場合、メソッドを Thread.Sleep 呼び出すと 5 ミリ秒の遅延が発生します。 次の例は、呼び出し後にのみプロパティが DateTime.Now.Milliseconds 変更して返されるミリ秒数を Thread.Sleep示しています。

string output = "";
for (int ctr = 0; ctr <= 20; ctr++)
{
    output += String.Format($"{DateTime.Now.Millisecond}\n");
    // Introduce a delay loop.
    for (int delay = 0; delay <= 1000; delay++)
    { }

    if (ctr == 10)
    {
        output += "Thread.Sleep called...\n";
        System.Threading.Thread.Sleep(5);
    }
}
Console.WriteLine(output);
// Press "Run" to see the output.
let mutable output = ""
for i = 0 to 20 do
    output <- output + $"{DateTime.Now.Millisecond}\n"
    // Introduce a delay loop.
    for _ = 0 to 1000 do ()

    if i = 10 then
        output <- output + "Thread.Sleep called...\n"
        System.Threading.Thread.Sleep 5

printfn $"{output}"
// Press "Run" to see the output.
Dim output As String = ""
For ctr As Integer = 0 To 20
    output += Date.Now.Millisecond.ToString() + vbCrLf
    ' Introduce a delay loop.
    For delay As Integer = 0 To 1000
    Next

    If ctr = 10 Then
        output += "Thread.Sleep called..." + vbCrLf
        Thread.Sleep(5)
    End If
Next
Console.WriteLine(output)
' The example displays output like the following:
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       Thread.Sleep called...
'       143
'       143
'       143
'       143
'       143
'       143
'       143
'       143
'       143
'       143

DateTime 操作

構造体を使用したDateTime計算 (またはSubtractなど) では、Add構造体の値は変更されません。 代わりに、計算は、その値が計算の結果である新しい DateTime 構造体を返します。

タイム ゾーン間の変換操作 (UTC とローカル時刻の間、またはタイム ゾーンと別のタイム ゾーン間など) では夏時間が考慮されますが、算術演算と比較操作では考慮されません。

構造体自体では、あるタイム ゾーンから別のタイム ゾーンへの変換のサポートが DateTime 制限されています。 このメソッドを ToLocalTime 使用して UTC を現地時刻に変換することも、メソッドを ToUniversalTime 使用して現地時刻から UTC に変換することもできます。 ただし、このクラスでは、タイム ゾーン変換メソッドの完全なセットを TimeZoneInfo 使用できます。 これらのメソッドを使用して、世界のいずれかのタイム ゾーンの時刻を他のタイム ゾーンの時刻に変換します。

オブジェクトの DateTime 計算と比較は、オブジェクトが同じタイム ゾーン内の時刻を表す場合にのみ意味があります。 オブジェクトを TimeZoneInfo 使用して値のタイム ゾーンを DateTime 表すことができますが、2 つは疎結合されています。 DateTimeオブジェクトには、その日付と時刻の値のタイム ゾーンを表すオブジェクトを返すプロパティがありません。 このプロパティは KindDateTime UTC、現地時刻、または指定されていないかどうかを示します。 タイム ゾーン対応アプリケーションでは、オブジェクトが作成されたタイム ゾーンを特定するために、外部メカニズムに依存する DateTime 必要があります。 値と値のタイム ゾーンを表すオブジェクトの DateTime 両方を TimeZoneInfo ラップする構造体を DateTime 使用できます。 計算での UTC の使用と値とのDateTime比較の詳細については、「日付と時刻を使用した算術演算の実行」を参照してください

DateTime メンバーは、グレゴリオ暦を暗黙的に使用してその操作を実行します。 例外は、カレンダーを暗黙的に指定するメソッドです。 これには、カレンダーを指定するコンストラクターや、派生 IFormatProviderするパラメーターを持つメソッドが含まれます。次に例を示 System.Globalization.DateTimeFormatInfoします。

型のメンバーによる操作では、 DateTime 閏年や 1 か月の日数などの詳細が考慮されます。

DateTime の値とカレンダー

.NET クラス ライブラリには、クラスから Calendar 派生したカレンダー クラスが多数含まれています。 これらは次のとおりです。

重要

和暦の時代 (年号) は天皇の代に基づいているため、変更されることが予想されます。 たとえば、JapaneseCalendarJapaneseLunisolarCalendar において、2019 年 5 月 1 日から令和時代が始まることになりました。 このような時代 (年号) の変更は、これらのカレンダーを使用するすべてのアプリケーションに影響します。 詳細およびアプリケーションが影響を受けるかどうかを判断するには、「.NET の日本語カレンダーでの新しい時代 (年号) の処理」を参照してください。 Windows システムでアプリケーションをテストし、時代 (年号) の変更に対する準備を行う方法については、「日本の時代 (年号) に合わせてアプリケーションを準備する」を参照してください。 複数の時代 (年号) を含むカレンダーをサポートする .NET の機能と、複数の時代 (年号) をサポートするカレンダーを使用する場合のベスト プラクティスについては、「年号の使用」を参照してください

各カルチャでは、読み取り専用 CultureInfo.Calendar プロパティで定義された既定のカレンダーが使用されます。 各カルチャでは、読み取り専用 CultureInfo.OptionalCalendars プロパティで定義された 1 つ以上の予定表をサポートできます。 特定 CultureInfo のオブジェクトで現在使用されているカレンダーは、その DateTimeFormatInfo.Calendar プロパティによって定義されます。 配列内 CultureInfo.OptionalCalendars にあるカレンダーのいずれかである必要があります。

カルチャの現在のカレンダーは、そのカルチャのすべての書式設定操作で使用されます。 たとえば、タイ仏教文化の既定の暦は、クラスによって ThaiBuddhistCalendar 表されるタイ仏教時代の暦です。 タイ仏教文化を CultureInfo 表すオブジェクトが日付と時刻の書式設定操作で使用されている場合、既定では、タイ仏教時代暦が使用されます。 グレゴリオ暦は、次の例に示すように、カルチャの DateTimeFormatInfo.Calendar プロパティが変更された場合にのみ使用されます。

var thTH = new System.Globalization.CultureInfo("th-TH");
var value = new DateTime(2016, 5, 28);

Console.WriteLine(value.ToString(thTH));

thTH.DateTimeFormat.Calendar = new System.Globalization.GregorianCalendar();
Console.WriteLine(value.ToString(thTH));
// The example displays the following output:
//       28/5/2559 0:00:00
//       28/5/2016 0:00:00
let thTH = System.Globalization.CultureInfo "th-TH"
let value = DateTime(2016, 5, 28)

printfn $"{value.ToString thTH}"

thTH.DateTimeFormat.Calendar <- System.Globalization.GregorianCalendar()

printfn $"{value.ToString thTH}"

// The example displays the following output:
//       28/5/2559 0:00:00
//       28/5/2016 0:00:00
Dim thTH As New CultureInfo("th-TH")
Dim value As New DateTime(2016, 5, 28)

Console.WriteLine(value.ToString(thTH))

thTH.DateTimeFormat.Calendar = New GregorianCalendar()
Console.WriteLine(value.ToString(thTH))
' The example displays the following output:
'       28/5/2559 0:00:00
'       28/5/2016 0:00:00

次の例に示すように、カルチャの現在のカレンダーは、そのカルチャのすべての解析操作でも使用されます。

var thTH = new System.Globalization.CultureInfo("th-TH");
var value = DateTime.Parse("28/05/2559", thTH);
Console.WriteLine(value.ToString(thTH));

thTH.DateTimeFormat.Calendar = new System.Globalization.GregorianCalendar();
Console.WriteLine(value.ToString(thTH));
// The example displays the following output:
//       28/5/2559 0:00:00
//       28/5/2016 0:00:00
let thTH = System.Globalization.CultureInfo "th-TH"
let value = DateTime.Parse("28/05/2559", thTH)
printfn $"{value.ToString thTH}"

thTH.DateTimeFormat.Calendar <- System.Globalization.GregorianCalendar()
printfn $"{value.ToString thTH}"

// The example displays the following output:
//       28/5/2559 0:00:00
//       28/5/2016 0:00:00
Private Sub ThaiBuddhistEraParse()
    Dim thTH As New CultureInfo("th-TH")
    Dim value As DateTime = DateTime.Parse("28/5/2559", thTH)
    Console.WriteLine(value.ToString(thTH))

    thTH.DateTimeFormat.Calendar = New GregorianCalendar()
    Console.WriteLine(value.ToString(thTH))
    ' The example displays the following output:
    '       28/5/2559 0:00:00
    '       28/5/2016 0:00:00
End Sub

パラメーターをDateTime含む calendar DateTime コンストラクターを呼び出し、そのカレンダーを表すオブジェクトを渡Calendarすことによって、特定のカレンダーの日付と時刻の要素 (年、月、日の数) を使用して値をインスタンス化します。 次の例では、カレンダーの日付と時刻の要素を ThaiBuddhistCalendar 使用します。

var thTH = new System.Globalization.CultureInfo("th-TH");
var dat = new DateTime(2559, 5, 28, thTH.DateTimeFormat.Calendar);
Console.WriteLine($"Thai Buddhist era date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Gregorian date:   {dat:d}");
// The example displays the following output:
//       Thai Buddhist Era Date:  28/5/2559
//       Gregorian Date:     28/05/2016
let thTH = System.Globalization.CultureInfo "th-TH"
let dat = DateTime(2559, 5, 28, thTH.DateTimeFormat.Calendar)

printfn $"""Thai Buddhist era date: {dat.ToString("d", thTH)}"""
printfn $"Gregorian date:   {dat:d}"

// The example displays the following output:
//       Thai Buddhist Era Date:  28/5/2559
//       Gregorian Date:     28/05/2016
Dim thTH As New CultureInfo("th-TH")
Dim dat As New DateTime(2559, 5, 28, thTH.DateTimeFormat.Calendar)
Console.WriteLine($"Thai Buddhist Era date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Gregorian date:   {dat:d}")
' The example displays the following output:
'       Thai Buddhist Era Date:  28/5/2559
'       Gregorian Date:     28/05/2016

DateTime パラメーターを含 calendar まないコンストラクターは、日付と時刻の要素がグレゴリオ暦の単位として表されることを前提としています。

その他 DateTime のすべてのプロパティとメソッドでは、グレゴリオ暦が使用されます。 たとえば、プロパティは DateTime.Year グレゴリオ暦の年を返し DateTime.IsLeapYear(Int32) 、このメソッドはパラメーターがグレゴリオ暦の年であることを year 前提としています。 グレゴリオ暦を使用する各 DateTime メンバーには、特定のカレンダーを使用するクラスの Calendar 対応するメンバーがあります。 たとえば、メソッドは特定の Calendar.GetYear カレンダーの年を返し Calendar.IsLeapYear 、メソッドはパラメーターを year 特定のカレンダーの年番号として解釈します。 次の例では、クラスの DateTime メンバーと対応するメンバーの両方を ThaiBuddhistCalendar 使用します。

var thTH = new System.Globalization.CultureInfo("th-TH");
var cal = thTH.DateTimeFormat.Calendar;
var dat = new DateTime(2559, 5, 28, cal);
Console.WriteLine("Using the Thai Buddhist Era calendar:");
Console.WriteLine($"Date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Year: {cal.GetYear(dat)}");
Console.WriteLine($"Leap year: {cal.IsLeapYear(cal.GetYear(dat))}\n");

Console.WriteLine("Using the Gregorian calendar:");
Console.WriteLine($"Date: {dat:d}");
Console.WriteLine($"Year: {dat.Year}");
Console.WriteLine($"Leap year: {DateTime.IsLeapYear(dat.Year)}");
// The example displays the following output:
//       Using the Thai Buddhist Era calendar
//       Date :   28/5/2559
//       Year: 2559
//       Leap year :   True
//
//       Using the Gregorian calendar
//       Date :   28/05/2016
//       Year: 2016
//       Leap year :   True
let thTH = System.Globalization.CultureInfo "th-TH"
let cal = thTH.DateTimeFormat.Calendar
let dat = DateTime(2559, 5, 28, cal)
printfn "Using the Thai Buddhist Era calendar:"
printfn $"""Date: {dat.ToString("d", thTH)}"""
printfn $"Year: {cal.GetYear dat}"
printfn $"Leap year: {cal.IsLeapYear(cal.GetYear dat)}\n"

printfn "Using the Gregorian calendar:"
printfn $"Date: {dat:d}"
printfn $"Year: {dat.Year}"
printfn $"Leap year: {DateTime.IsLeapYear dat.Year}"

// The example displays the following output:
//       Using the Thai Buddhist Era calendar
//       Date :   28/5/2559
//       Year: 2559
//       Leap year :   True
//
//       Using the Gregorian calendar
//       Date :   28/05/2016
//       Year: 2016
//       Leap year :   True
Dim thTH As New CultureInfo("th-TH")
Dim cal As Calendar = thTH.DateTimeFormat.Calendar
Dim dat As New DateTime(2559, 5, 28, cal)
Console.WriteLine("Using the Thai Buddhist Era calendar:")
Console.WriteLine($"Date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Year: {cal.GetYear(dat)}")
Console.WriteLine($"Leap year: {cal.IsLeapYear(cal.GetYear(dat))}")
Console.WriteLine()

Console.WriteLine("Using the Gregorian calendar:")
Console.WriteLine($"Date: {dat:d}")
Console.WriteLine($"Year: {dat.Year}")
Console.WriteLine($"Leap year: {DateTime.IsLeapYear(dat.Year)}")
' The example displays the following output:
'       Using the Thai Buddhist Era calendar
'       Date :   28/5/2559
'       Year: 2559
'       Leap year :   True
'
'       Using the Gregorian calendar
'       Date :   28/05/2016
'       Year: 2016
'       Leap year :   True

構造体 DateTime には、 DayOfWeek グレゴリオ暦の曜日を返すプロパティが含まれています。 年の週番号を取得できるメンバーは含まれません。 年の週を取得するには、個々のカレンダーの Calendar.GetWeekOfYear メソッドを呼び出します。 具体的な例を次に示します。

var thTH = new System.Globalization.CultureInfo("th-TH");
var thCalendar = thTH.DateTimeFormat.Calendar;
var dat = new DateTime(1395, 8, 18, thCalendar);
Console.WriteLine("Using the Thai Buddhist Era calendar:");
Console.WriteLine($"Date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Day of Week: {thCalendar.GetDayOfWeek(dat)}");
Console.WriteLine($"Week of year: {thCalendar.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}\n");

var greg = new System.Globalization.GregorianCalendar();
Console.WriteLine("Using the Gregorian calendar:");
Console.WriteLine($"Date: {dat:d}");
Console.WriteLine($"Day of Week: {dat.DayOfWeek}");
Console.WriteLine($"Week of year: {greg.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay,DayOfWeek.Sunday)}");
// The example displays the following output:
//       Using the Thai Buddhist Era calendar
//       Date :  18/8/1395
//       Day of Week: Sunday
//       Week of year: 34
//
//       Using the Gregorian calendar
//       Date :  18/08/0852
//       Day of Week: Sunday
//       Week of year: 34
let thTH = System.Globalization.CultureInfo "th-TH"
let thCalendar = thTH.DateTimeFormat.Calendar
let dat = DateTime(1395, 8, 18, thCalendar)
printfn "Using the Thai Buddhist Era calendar:"
printfn $"""Date: {dat.ToString("d", thTH)}"""
printfn $"Day of Week: {thCalendar.GetDayOfWeek dat}"
printfn $"Week of year: {thCalendar.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}\n"

let greg = System.Globalization.GregorianCalendar()
printfn "Using the Gregorian calendar:"
printfn $"Date: {dat:d}"
printfn $"Day of Week: {dat.DayOfWeek}"
printfn $"Week of year: {greg.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}"

// The example displays the following output:
//       Using the Thai Buddhist Era calendar
//       Date :  18/8/1395
//       Day of Week: Sunday
//       Week of year: 34
//
//       Using the Gregorian calendar
//       Date :  18/08/0852
//       Day of Week: Sunday
//       Week of year: 34
Dim thTH As New CultureInfo("th-TH")
Dim thCalendar As Calendar = thTH.DateTimeFormat.Calendar
Dim dat As New DateTime(1395, 8, 18, thCalendar)
Console.WriteLine("Using the Thai Buddhist Era calendar:")
Console.WriteLine($"Date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Day of Week: {thCalendar.GetDayOfWeek(dat)}")
Console.WriteLine($"Week of year: {thCalendar.GetWeekOfYear(dat, CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}")
Console.WriteLine()

Dim greg As Calendar = New GregorianCalendar()
Console.WriteLine("Using the Gregorian calendar:")
Console.WriteLine($"Date: {dat:d}")
Console.WriteLine($"Day of Week: {dat.DayOfWeek}")
Console.WriteLine($"Week of year: {greg.GetWeekOfYear(dat, CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}")
' The example displays the following output:
'       Using the Thai Buddhist Era calendar
'       Date :  18/8/1395
'       Day of Week: Sunday
'       Week of year: 34
'       
'       Using the Gregorian calendar
'       Date :  18/08/0852
'       Day of Week: Sunday
'       Week of year: 34

日付とカレンダーの詳細については、「カレンダーの操作」を参照してください

DateTime 値を保持する

次の方法で値を保持 DateTime できます。

選択した手法に関係なく、値を DateTime 復元するルーチンがデータを失ったり、例外をスローしたりしないようにする必要があります。 DateTime 値はラウンドトリップする必要があります。 つまり、元の値と復元された値は同じである必要があります。 また、元 DateTime の値が 1 回の時間を表す場合は、復元されたのと同じ時刻を識別する必要があります。

値を文字列として保持する

文字列として保持されている値を正常に復元 DateTime するには、次の規則に従います。

  • 文字列を永続化したときと同じように、カルチャ固有の書式を復元する場合と同じ前提を設定します。 現在のカルチャが保存されたシステムのカルチャと異なるシステムで文字列を復元できるようにするには、オーバーロードを呼び出 ToString して、インバリアント カルチャの規則を使用して文字列を保存します。 インバリアント カルチャの Parse(String, IFormatProvider, DateTimeStyles) 規則を使用して文字列を復元するには、or TryParse(String, IFormatProvider, DateTimeStyles, DateTime) オーバーロードを呼び出します。 現在のカルチャの規則を ToString()使用する 、 Parse(String)または TryParse(String, DateTime) オーバーロードは使用しないでください。

  • 日付が 1 つの時刻の瞬間を表す場合は、別のタイム ゾーンであっても、復元された時刻と同じ瞬間を表すようにします。 値を DateTime 保存または使用 DateTimeOffsetする前に、協定世界時 (UTC) に変換します。

文字列として値を永続化するときに発生する DateTime 最も一般的なエラーは、既定または現在のカルチャの書式設定規則に依存することです。 文字列を保存および復元するときに、現在のカルチャが異なる場合に問題が発生します。 次の例は、これらの問題を示しています。 現在のカルチャの書式設定規則を使用して 5 つの日付を保存します。この場合は英語 (米国)。 別のカルチャの書式設定規則を使用して日付を復元します。この場合は英語 (英国) です。 2 つのカルチャの書式設定規則が異なるため、2 つの日付を復元することはできません。また、再メイン 3 つの日付は正しく解釈されません。 また、元の日付と時刻の値が 1 つの時点を表している場合、タイム ゾーン情報が失われるため、復元された時刻は正しくありません。

public static void PersistAsLocalStrings()
{
    SaveLocalDatesAsString();
    RestoreLocalDatesFromString();
}

private static void SaveLocalDatesAsString()
{
    DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
                   new DateTime(2014, 7, 10, 23, 49, 0),
                   new DateTime(2015, 1, 10, 1, 16, 0),
                   new DateTime(2014, 12, 20, 21, 45, 0),
                   new DateTime(2014, 6, 2, 15, 14, 0) };
    string? output = null;

    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    for (int ctr = 0; ctr < dates.Length; ctr++)
    {
        Console.WriteLine(dates[ctr].ToString("f"));
        output += dates[ctr].ToString() + (ctr != dates.Length - 1 ? "|" : "");
    }
    var sw = new StreamWriter(filenameTxt);
    sw.Write(output);
    sw.Close();
    Console.WriteLine("Saved dates...");
}

private static void RestoreLocalDatesFromString()
{
    TimeZoneInfo.ClearCachedData();
    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
    StreamReader sr = new StreamReader(filenameTxt);
    string[] inputValues = sr.ReadToEnd().Split(new char[] { '|' },
                                                StringSplitOptions.RemoveEmptyEntries);
    sr.Close();
    Console.WriteLine("The dates on an {0} system:",
                      Thread.CurrentThread.CurrentCulture.Name);
    foreach (var inputValue in inputValues)
    {
        DateTime dateValue;
        if (DateTime.TryParse(inputValue, out dateValue))
        {
            Console.WriteLine($"'{inputValue}' --> {dateValue:f}");
        }
        else
        {
            Console.WriteLine($"Cannot parse '{inputValue}'");
        }
    }
    Console.WriteLine("Restored dates...");
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       Cannot parse //6/14/2014 6:32:00 AM//
//       //7/10/2014 11:49:00 PM// --> 07 October 2014 23:49
//       //1/10/2015 1:16:00 AM// --> 01 October 2015 01:16
//       Cannot parse //12/20/2014 9:45:00 PM//
//       //6/2/2014 3:14:00 PM// --> 06 February 2014 15:14
//       Restored dates...
let saveLocalDatesAsString () =
    let dates = 
        [ DateTime(2014, 6, 14, 6, 32, 0)
          DateTime(2014, 7, 10, 23, 49, 0)
          DateTime(2015, 1, 10, 1, 16, 0)
          DateTime(2014, 12, 20, 21, 45, 0)
          DateTime(2014, 6, 2, 15, 14, 0) ]

    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"

    let output =
        [ for date in dates do
            printfn $"{date}"
            string date ]
        |> String.concat "|"

    use sw = new StreamWriter(filenameTxt)
    sw.Write output
    printfn "Saved dates..."

let restoreLocalDatesFromString () =
    TimeZoneInfo.ClearCachedData()
    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "en-GB"

    use sr = new StreamReader(filenameTxt)
    let inputValues = 
        sr.ReadToEnd().Split('|', StringSplitOptions.RemoveEmptyEntries)

    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"

    for inputValue in inputValues do
        match DateTime.TryParse inputValue with
        | true, dateValue ->
            printfn $"'{inputValue}' --> {dateValue:f}"
        | _ ->
            printfn $"Cannot parse '{inputValue}'"

    printfn "Restored dates..."

let persistAsLocalStrings () =
    saveLocalDatesAsString ()
    restoreLocalDatesFromString ()

// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       Cannot parse //6/14/2014 6:32:00 AM//
//       //7/10/2014 11:49:00 PM// --> 07 October 2014 23:49
//       //1/10/2015 1:16:00 AM// --> 01 October 2015 01:16
//       Cannot parse //12/20/2014 9:45:00 PM//
//       //6/2/2014 3:14:00 PM// --> 06 February 2014 15:14
//       Restored dates...

値を正常にラウンドトリップ DateTime するには、次の手順に従います。

  1. 値が 1 つの時刻の瞬間を表す場合は、メソッドを呼び出 ToUniversalTime してローカル時刻から UTC に変換します。
  2. またはString.Format(IFormatProvider, String, Object[])オーバーロードを呼び出して、日付を文字列形式にToString(String, IFormatProvider)変換します。 引数として指定して、インバリアント カルチャの書式設定規則をCultureInfo.InvariantCultureprovider使用します。 "O" または "R" 標準書式指定文字列を使用して値をラウンドトリップすることを指定します。

データを失わずに永続化された DateTime 値を復元するには、次の手順に従います。

  1. or TryParseExact オーバーロードを呼び出してデータをParseExact解析します。 引数としてprovider指定CultureInfo.InvariantCultureし、変換時に引数に使用したのと同じ標準書式指定文字列をformat使用します。 引数に DateTimeStyles.RoundtripKind 値を styles 含めます。
  2. 値が DateTime 1 つの時点を表す場合は、メソッドを ToLocalTime 呼び出して、解析された日付を UTC から現地時刻に変換します。

次の例では、インバリアント カルチャと "O" 標準書式指定文字列を使用して、ソース システムとターゲット システムのシステム、カルチャ、タイム ゾーンに関係なく、保存および復元された値が同じ時点を表すように DateTime します。

public static void PersistAsInvariantStrings()
{
    SaveDatesAsInvariantStrings();
    RestoreDatesAsInvariantStrings();
}

private static void SaveDatesAsInvariantStrings()
{
    DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
                   new DateTime(2014, 7, 10, 23, 49, 0),
                   new DateTime(2015, 1, 10, 1, 16, 0),
                   new DateTime(2014, 12, 20, 21, 45, 0),
                   new DateTime(2014, 6, 2, 15, 14, 0) };
    string? output = null;

    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    for (int ctr = 0; ctr < dates.Length; ctr++)
    {
        Console.WriteLine(dates[ctr].ToString("f"));
        output += dates[ctr].ToUniversalTime().ToString("O", CultureInfo.InvariantCulture)
                  + (ctr != dates.Length - 1 ? "|" : "");
    }
    var sw = new StreamWriter(filenameTxt);
    sw.Write(output);
    sw.Close();
    Console.WriteLine("Saved dates...");
}

private static void RestoreDatesAsInvariantStrings()
{
    TimeZoneInfo.ClearCachedData();
    Console.WriteLine("Current Time Zone: {0}",
                      TimeZoneInfo.Local.DisplayName);
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
    StreamReader sr = new StreamReader(filenameTxt);
    string[] inputValues = sr.ReadToEnd().Split(new char[] { '|' },
                                                StringSplitOptions.RemoveEmptyEntries);
    sr.Close();
    Console.WriteLine("The dates on an {0} system:",
                      Thread.CurrentThread.CurrentCulture.Name);
    foreach (var inputValue in inputValues)
    {
        DateTime dateValue;
        if (DateTime.TryParseExact(inputValue, "O", CultureInfo.InvariantCulture,
                              DateTimeStyles.RoundtripKind, out dateValue))
        {
            Console.WriteLine($"'{inputValue}' --> {dateValue.ToLocalTime():f}");
        }
        else
        {
            Console.WriteLine("Cannot parse '{0}'", inputValue);
        }
    }
    Console.WriteLine("Restored dates...");
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       '2014-06-14T13:32:00.0000000Z' --> 14 June 2014 14:32
//       '2014-07-11T06:49:00.0000000Z' --> 11 July 2014 07:49
//       '2015-01-10T09:16:00.0000000Z' --> 10 January 2015 09:16
//       '2014-12-21T05:45:00.0000000Z' --> 21 December 2014 05:45
//       '2014-06-02T22:14:00.0000000Z' --> 02 June 2014 23:14
//       Restored dates...
let saveDatesAsInvariantStrings () =
    let dates = 
        [ DateTime(2014, 6, 14, 6, 32, 0)
          DateTime(2014, 7, 10, 23, 49, 0)
          DateTime(2015, 1, 10, 1, 16, 0)
          DateTime(2014, 12, 20, 21, 45, 0)
          DateTime(2014, 6, 2, 15, 14, 0) ]

    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"

    let output =
        [ for date in dates do
            printfn $"{date:f}"
            date.ToUniversalTime().ToString("O", CultureInfo.InvariantCulture) ]
        |> String.concat "|"

    use sw = new StreamWriter(filenameTxt)
    sw.Write output
    printfn "Saved dates..."

let restoreDatesAsInvariantStrings () =
    TimeZoneInfo.ClearCachedData()
    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "en-GB"
    
    use sr = new StreamReader(filenameTxt)
    let inputValues = 
        sr.ReadToEnd().Split('|', StringSplitOptions.RemoveEmptyEntries)

    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"

    for inputValue in inputValues do
        match DateTime.TryParseExact(inputValue, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind) with
        | true, dateValue ->
            printfn $"'{inputValue}' --> {dateValue.ToLocalTime():f}"
        | _ ->
            printfn $"Cannot parse '{inputValue}'"

    printfn "Restored dates..."

let persistAsInvariantStrings () =
    saveDatesAsInvariantStrings ()
    restoreDatesAsInvariantStrings ()

// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       '2014-06-14T13:32:00.0000000Z' --> 14 June 2014 14:32
//       '2014-07-11T06:49:00.0000000Z' --> 11 July 2014 07:49
//       '2015-01-10T09:16:00.0000000Z' --> 10 January 2015 09:16
//       '2014-12-21T05:45:00.0000000Z' --> 21 December 2014 05:45
//       '2014-06-02T22:14:00.0000000Z' --> 02 June 2014 23:14
//       Restored dates...

値を整数として保持する

日付と時刻は、ティック数を Int64 表す値として保持できます。 この場合、値が永続化および復元されるシステムのカルチャを DateTime 考慮する必要はありません。

値を DateTime 整数として保持するには:

  1. 値が DateTime 1 つの瞬間を表す場合は、メソッドを呼び出 ToUniversalTime して UTC に変換します。
  2. プロパティから値によって表されるティックの数をDateTimeTicks取得します。

整数として保持されている値を復元 DateTime するには:

  1. コンストラクターに値を渡Int64して、新しいDateTimeオブジェクトをDateTime(Int64)インスタンス化します。
  2. 値が DateTime 1 つの時点を表す場合は、メソッドを呼び出して UTC から現地時刻に ToLocalTime 変換します。

次の例では、米国太平洋タイム ゾーンの DateTime システムで整数として値の配列を保持します。 UTC ゾーン内のシステムで復元します。 整数を含むファイルには、その直後の値のInt64合計数を示す値が含まれていますInt32

public static void PersistAsIntegers()
{
    SaveDatesAsInts();
    RestoreDatesAsInts();
}

private static void SaveDatesAsInts()
{
    DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
                   new DateTime(2014, 7, 10, 23, 49, 0),
                   new DateTime(2015, 1, 10, 1, 16, 0),
                   new DateTime(2014, 12, 20, 21, 45, 0),
                   new DateTime(2014, 6, 2, 15, 14, 0) };

    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    var ticks = new long[dates.Length];
    for (int ctr = 0; ctr < dates.Length; ctr++)
    {
        Console.WriteLine(dates[ctr].ToString("f"));
        ticks[ctr] = dates[ctr].ToUniversalTime().Ticks;
    }
    var fs = new FileStream(filenameInts, FileMode.Create);
    var bw = new BinaryWriter(fs);
    bw.Write(ticks.Length);
    foreach (var tick in ticks)
        bw.Write(tick);

    bw.Close();
    Console.WriteLine("Saved dates...");
}

private static void RestoreDatesAsInts()
{
    TimeZoneInfo.ClearCachedData();
    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
    FileStream fs = new FileStream(filenameInts, FileMode.Open);
    BinaryReader br = new BinaryReader(fs);
    int items;
    DateTime[] dates;

    try
    {
        items = br.ReadInt32();
        dates = new DateTime[items];

        for (int ctr = 0; ctr < items; ctr++)
        {
            long ticks = br.ReadInt64();
            dates[ctr] = new DateTime(ticks).ToLocalTime();
        }
    }
    catch (EndOfStreamException)
    {
        Console.WriteLine("File corruption detected. Unable to restore data...");
        return;
    }
    catch (IOException)
    {
        Console.WriteLine("Unspecified I/O error. Unable to restore data...");
        return;
    }
    // Thrown during array initialization.
    catch (OutOfMemoryException)
    {
        Console.WriteLine("File corruption detected. Unable to restore data...");
        return;
    }
    finally
    {
        br.Close();
    }

    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    foreach (var value in dates)
        Console.WriteLine(value.ToString("f"));

    Console.WriteLine("Restored dates...");
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       14 June 2014 14:32
//       11 July 2014 07:49
//       10 January 2015 09:16
//       21 December 2014 05:45
//       02 June 2014 23:14
//       Restored dates...
let saveDatesAsInts () =
    let dates = 
        [ DateTime(2014, 6, 14, 6, 32, 0)
          DateTime(2014, 7, 10, 23, 49, 0)
          DateTime(2015, 1, 10, 1, 16, 0)
          DateTime(2014, 12, 20, 21, 45, 0)
          DateTime(2014, 6, 2, 15, 14, 0) ]

    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"
    let ticks =
        [| for date in dates do
            printfn $"{date:f}"
            date.ToUniversalTime().Ticks |]
    use fs = new FileStream(filenameInts, FileMode.Create)
    use bw = new BinaryWriter(fs)
    bw.Write ticks.Length

    for tick in ticks do
        bw.Write tick

    printfn "Saved dates..."

let restoreDatesAsInts () =
    TimeZoneInfo.ClearCachedData()
    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "en-GB"
    use fs = new FileStream(filenameInts, FileMode.Open)
    use br = new BinaryReader(fs)

    try
        let items = br.ReadInt32()
        let dates =
            [| for _ in 0..items do
                let ticks = br.ReadInt64()
                DateTime(ticks).ToLocalTime() |]

        printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"
        for value in dates do
            printfn $"{value:f}"
    with 
    | :? EndOfStreamException ->
        printfn "File corruption detected. Unable to restore data..."
    | :? IOException ->
        printfn "Unspecified I/O error. Unable to restore data..."
    // Thrown during array initialization.
    | :? OutOfMemoryException ->
        printfn"File corruption detected. Unable to restore data..."

    printfn "Restored dates..."

let persistAsIntegers () =
    saveDatesAsInts ()
    restoreDatesAsInts ()

// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       14 June 2014 14:32
//       11 July 2014 07:49
//       10 January 2015 09:16
//       21 December 2014 05:45
//       02 June 2014 23:14
//       Restored dates...

DateTime 値をシリアル化する

ストリームまたはファイルへのシリアル化によって値を保持 DateTime し、逆シリアル化を使用して値を復元できます。 DateTime データは、指定されたオブジェクト形式でシリアル化されます。 オブジェクトは逆シリアル化されるときに復元されます。 フォーマッタまたはシリアライザー (またはなどJsonSerializerXmlSerializer) は、シリアル化と逆シリアル化のプロセスを処理します。 シリアル化の詳細と、.NET でサポートされるシリアル化の種類については、「シリアル化」を参照してください

次の例では、クラスを XmlSerializer 使用して値をシリアル化および逆シリアル化 DateTime します。 この値は、21 世紀のすべての閏年の日を表します。 現在のカルチャが英語 (英国) のシステムで例が実行されている場合、出力は結果を表します。 オブジェクト自体を DateTime 逆シリアル化したため、コードは日付と時刻の形式のカルチャの違いを処理する必要はありません。

public static void PersistAsXML()
{
    // Serialize the data.
    var leapYears = new List<DateTime>();
    for (int year = 2000; year <= 2100; year += 4)
    {
        if (DateTime.IsLeapYear(year))
            leapYears.Add(new DateTime(year, 2, 29));
    }
    DateTime[] dateArray = leapYears.ToArray();

    var serializer = new XmlSerializer(dateArray.GetType());
    TextWriter sw = new StreamWriter(filenameXml);

    try
    {
        serializer.Serialize(sw, dateArray);
    }
    catch (InvalidOperationException e)
    {
        Console.WriteLine(e.InnerException?.Message);
    }
    finally
    {
        if (sw != null) sw.Close();
    }

    // Deserialize the data.
    DateTime[]? deserializedDates;
    using (var fs = new FileStream(filenameXml, FileMode.Open))
    {
        deserializedDates = (DateTime[]?)serializer.Deserialize(fs);
    }

    // Display the dates.
    Console.WriteLine($"Leap year days from 2000-2100 on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    int nItems = 0;
    if (deserializedDates is not null)
    {
        foreach (var dat in deserializedDates)
        {
            Console.Write($"   {dat:d}     ");
            nItems++;
            if (nItems % 5 == 0)
                Console.WriteLine();
        }
    }
}
// The example displays the following output:
//    Leap year days from 2000-2100 on an en-GB system:
//       29/02/2000       29/02/2004       29/02/2008       29/02/2012       29/02/2016
//       29/02/2020       29/02/2024       29/02/2028       29/02/2032       29/02/2036
//       29/02/2040       29/02/2044       29/02/2048       29/02/2052       29/02/2056
//       29/02/2060       29/02/2064       29/02/2068       29/02/2072       29/02/2076
//       29/02/2080       29/02/2084       29/02/2088       29/02/2092       29/02/2096
let persistAsXML () =
    // Serialize the data.
    let leapYears =
        [| for year in 2000..4..2100 do
            if DateTime.IsLeapYear year then
                DateTime(year, 2, 29) |]

    let serializer = XmlSerializer(leapYears.GetType())
    use sw = new StreamWriter(filenameXml)

    try
        serializer.Serialize(sw, leapYears)
    with :? InvalidOperationException as e ->
        printfn $"{e.InnerException.Message}"

    // Deserialize the data.
    use fs = new FileStream(filenameXml, FileMode.Open)
        
    let deserializedDates = serializer.Deserialize fs :?> DateTime []

    // Display the dates.
    printfn $"Leap year days from 2000-2100 on an {Thread.CurrentThread.CurrentCulture.Name} system:"
    
    let mutable nItems = 0
    for dat in deserializedDates do
        printf $"   {dat:d}     "
        nItems <- nItems + 1
        if nItems % 5 = 0 then
            printfn ""

// The example displays the following output:
//    Leap year days from 2000-2100 on an en-GB system:
//       29/02/2000       29/02/2004       29/02/2008       29/02/2012       29/02/2016
//       29/02/2020       29/02/2024       29/02/2028       29/02/2032       29/02/2036
//       29/02/2040       29/02/2044       29/02/2048       29/02/2052       29/02/2056
//       29/02/2060       29/02/2064       29/02/2068       29/02/2072       29/02/2076
//       29/02/2080       29/02/2084       29/02/2088       29/02/2092       29/02/2096

前の例には時間情報は含まれていません。 値が DateTime 一瞬の時間を表し、現地時刻として表される場合は、メソッドを呼び出 ToUniversalTime してシリアル化する前に、ローカル時刻から UTC に変換します。 逆シリアル化した後、メソッドを呼び出して UTC から現地時刻に ToLocalTime 変換します。

DateTime と TimeSpan

値型とTimeSpan値型はDateTime、a DateTime が一瞬の時間を表すのに対し、a TimeSpan は時間間隔を表す点が異なります。 あるインスタンスを別のインスタンスから減算して、TimeSpanそれらの間のDateTime時間間隔を表すオブジェクトを取得できます。 または、現在DateTimeに正TimeSpanの値を追加して、将来の日付をDateTime表す値を取得することもできます。

オブジェクトの DateTime 時間間隔を加算または減算できます。 時間間隔は負または正の値にすることができ、ティック、秒、オブジェクト TimeSpan などの単位で表すことができます。

許容範囲内の等価性を比較する

値の DateTime 等価比較は正確です。 等しいと見なすには、2 つの値を同じティック数として表す必要があります。 多くのアプリケーションでは、多くの場合、その精度は不要であるか、間違っています。 多くの場合、オブジェクトがほぼ等しいかどうかをDateTimeテストする必要があります

次の例では、ほぼ同等 DateTime の値を比較する方法を示します。 等しいと宣言するときに、差の小さな余白を受け入れます。

public static bool RoughlyEquals(DateTime time, DateTime timeWithWindow, int windowInSeconds, int frequencyInSeconds)
{
    long delta = (long)((TimeSpan)(timeWithWindow - time)).TotalSeconds % frequencyInSeconds;
    delta = delta > windowInSeconds ? frequencyInSeconds - delta : delta;
    return Math.Abs(delta) < windowInSeconds;
}

public static void TestRoughlyEquals()
{
    int window = 10;
    int freq = 60 * 60 * 2; // 2 hours;

    DateTime d1 = DateTime.Now;

    DateTime d2 = d1.AddSeconds(2 * window);
    DateTime d3 = d1.AddSeconds(-2 * window);
    DateTime d4 = d1.AddSeconds(window / 2);
    DateTime d5 = d1.AddSeconds(-window / 2);

    DateTime d6 = (d1.AddHours(2)).AddSeconds(2 * window);
    DateTime d7 = (d1.AddHours(2)).AddSeconds(-2 * window);
    DateTime d8 = (d1.AddHours(2)).AddSeconds(window / 2);
    DateTime d9 = (d1.AddHours(2)).AddSeconds(-window / 2);

    Console.WriteLine($"d1 ({d1}) ~= d1 ({d1}): {RoughlyEquals(d1, d1, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d2 ({d2}): {RoughlyEquals(d1, d2, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d3 ({d3}): {RoughlyEquals(d1, d3, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d4 ({d4}): {RoughlyEquals(d1, d4, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d5 ({d5}): {RoughlyEquals(d1, d5, window, freq)}");

    Console.WriteLine($"d1 ({d1}) ~= d6 ({d6}): {RoughlyEquals(d1, d6, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d7 ({d7}): {RoughlyEquals(d1, d7, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d8 ({d8}): {RoughlyEquals(d1, d8, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d9 ({d9}): {RoughlyEquals(d1, d9, window, freq)}");
}
// The example displays output similar to the following:
//    d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True
let roughlyEquals (time: DateTime) (timeWithWindow: DateTime) windowInSeconds frequencyInSeconds =
    let delta = 
        int64 (timeWithWindow - time).TotalSeconds % frequencyInSeconds
    
    let delta = if delta > windowInSeconds then frequencyInSeconds - delta else delta
    abs delta < windowInSeconds

let testRoughlyEquals () =
    let window = 10
    let window' = 10.
    let freq = 60 * 60 * 2 // 2 hours

    let d1 = DateTime.Now

    let d2 = d1.AddSeconds(2. * window')
    let d3 = d1.AddSeconds(-2. * window')
    let d4 = d1.AddSeconds(window' / 2.)
    let d5 = d1.AddSeconds(-window' / 2.)

    let d6 = (d1.AddHours 2).AddSeconds(2. * window')
    let d7 = (d1.AddHours 2).AddSeconds(-2. * window')
    let d8 = (d1.AddHours 2).AddSeconds(window' / 2.)
    let d9 = (d1.AddHours 2).AddSeconds(-window' / 2.)

    printfn $"d1 ({d1}) ~= d1 ({d1}): {roughlyEquals d1 d1 window freq}"
    printfn $"d1 ({d1}) ~= d2 ({d2}): {roughlyEquals d1 d2 window freq}"
    printfn $"d1 ({d1}) ~= d3 ({d3}): {roughlyEquals d1 d3 window freq}"
    printfn $"d1 ({d1}) ~= d4 ({d4}): {roughlyEquals d1 d4 window freq}"
    printfn $"d1 ({d1}) ~= d5 ({d5}): {roughlyEquals d1 d5 window freq}"

    printfn $"d1 ({d1}) ~= d6 ({d6}): {roughlyEquals d1 d6 window freq}"
    printfn $"d1 ({d1}) ~= d7 ({d7}): {roughlyEquals d1 d7 window freq}"
    printfn $"d1 ({d1}) ~= d8 ({d8}): {roughlyEquals d1 d8 window freq}"
    printfn $"d1 ({d1}) ~= d9 ({d9}): {roughlyEquals d1 d9 window freq}"

// The example displays output similar to the following:
//    d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True
Public Shared Function RoughlyEquals(time As DateTime, timeWithWindow As DateTime,
                             windowInSeconds As Integer,
                             frequencyInSeconds As Integer) As Boolean
    Dim delta As Long = (timeWithWindow.Subtract(time)).TotalSeconds _
                                            Mod frequencyInSeconds

    If delta > windowInSeconds Then
        delta = frequencyInSeconds - delta
    End If

    Return Math.Abs(delta) < windowInSeconds
End Function

Public Shared Sub TestRoughlyEquals()
    Dim window As Integer = 10
    Dim freq As Integer = 60 * 60 * 2 ' 2 hours;
    Dim d1 As DateTime = DateTime.Now

    Dim d2 As DateTime = d1.AddSeconds(2 * window)
    Dim d3 As DateTime = d1.AddSeconds(-2 * window)
    Dim d4 As DateTime = d1.AddSeconds(window / 2)
    Dim d5 As DateTime = d1.AddSeconds(-window / 2)

    Dim d6 As DateTime = d1.AddHours(2).AddSeconds(2 * window)
    Dim d7 As DateTime = d1.AddHours(2).AddSeconds(-2 * window)
    Dim d8 As DateTime = d1.AddHours(2).AddSeconds(window / 2)
    Dim d9 As DateTime = d1.AddHours(2).AddSeconds(-window / 2)

    Console.WriteLine($"d1 ({d1}) ~= d1 ({d1}): {RoughlyEquals(d1, d1, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d2 ({d2}): {RoughlyEquals(d1, d2, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d3 ({d3}): {RoughlyEquals(d1, d3, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d4 ({d4}): {RoughlyEquals(d1, d4, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d5 ({d5}): {RoughlyEquals(d1, d5, window, freq)}")

    Console.WriteLine($"d1 ({d1}) ~= d6 ({d6}): {RoughlyEquals(d1, d6, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d7 ({d7}): {RoughlyEquals(d1, d7, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d8 ({d8}): {RoughlyEquals(d1, d8, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d9 ({d9}): {RoughlyEquals(d1, d9, window, freq)}")
End Sub
' The example displays output similar to the following:
'    d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
'    d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
'    d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
'    d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
'    d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
'    d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
'    d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
'    d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
'    d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True

COM 相互運用に関する考慮事項

DateTime COM アプリケーションに転送された後、マネージド アプリケーションに戻される値は、ラウンド トリップと言われます。 ただし、 DateTime 時刻のみを指定する値は、想定どおりにラウンドトリップしません。

午後 3 時などの時刻のみを往復する場合、最終日時は 1899 年 12 月 30 日午後 3 時、午後 1 時ではなく、午後 3 時 00 分です。NET と COM では、時刻のみが指定されている場合、既定の日付が想定されます。 ただし、COM システムは 1899 年 12 月 30 日の基準日を想定し、.NET では 0001 年 1 月 1 日の基準日を想定しています。

.NET から COM に時刻のみが渡されると、時刻を COM で使用される形式に変換する特別な処理が実行されます。 COM から .NET に時刻のみが渡された場合、1899 年 12 月 30 日以前に正当な日付と時刻が破損するため、特別な処理は実行されません。 日付が COM からのラウンド トリップを開始した場合、.NET と COM は日付を保持します。

.NET と COM の動作は、アプリケーションが時刻のみを指定するラウンドトリップを DateTime 行う場合、アプリケーションは最終 DateTime オブジェクトの誤った日付を変更または無視することを忘れてはならないことを意味します。