C# TryParseExactの使い方を完全解説|DateTime変換で失敗する原因と書式指定の実例

はじめに

C#で文字列の日付をDateTimeに変換するとき、よく使われるのがDateTime.TryParseExactです。

たとえば、次のような文字列を扱う場面があります。

C#
"2026/06/16"
"2026-06-16"
"20260616"
"2026-06-16 09:30:00"

これらは人間には日付だと分かりますが、C#では「どの形式の日付なのか」を正しく指定しないと、変換に失敗することがあります。

TryParseExactは、指定した書式と入力文字列が一致した場合だけDateTimeへ変換できるメソッドです。入力チェック、CSV取込、ログ解析、APIレスポンス処理など、実務でもよく使われます。

この記事では、C#のTryParseExactの基本構文、書式指定子、失敗する原因、複数フォーマットの扱い方、実務向けサンプルまで詳しく解説します。

1. C#のTryParseExactとは?DateTime変換で使う基本

1-1. TryParseExactの役割と「指定した書式どおりに変換する」意味

DateTime.TryParseExactは、文字列が指定した日付形式と完全に一致する場合にだけ、DateTime型へ変換するメソッドです。

たとえば、"2026/06/16"という文字列を"yyyy/MM/dd"という書式で変換する場合、文字列とフォーマットが一致しているため成功します。

C#
using System;
using System.Globalization;

string text = "2026/06/16";

bool success = DateTime.TryParseExact(
text,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime result
);

Console.WriteLine(success); // True
Console.WriteLine(result); // 2026/06/16 0:00:00

一方で、入力が"2026-06-16"なのに書式を"yyyy/MM/dd"にすると失敗します。

C#
string text = "2026-06-16";

bool success = DateTime.TryParseExact(
text,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime result
);

Console.WriteLine(success); // False

このように、TryParseExactは「日付として読めそうか」ではなく、「指定された書式と一致しているか」を厳密に判定します。

1-2. TryParse・Parse・ParseExactとの違い

C#には、文字列をDateTimeに変換するためのメソッドが複数あります。

Parseは変換に失敗すると例外が発生します。

C#
DateTime date = DateTime.Parse("2026/06/16");

TryParseは変換に失敗しても例外を出さず、戻り値のboolで成功・失敗を判定できます。

C#
bool success = DateTime.TryParse("2026/06/16", out DateTime date);

ParseExactは指定した書式に一致する場合だけ変換しますが、失敗すると例外が発生します。

C#
DateTime date = DateTime.ParseExact(
"2026/06/16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture
);

TryParseExactは、指定した書式に一致する場合だけ変換し、失敗しても例外を出しません。

C#
bool success = DateTime.TryParseExact(
"2026/06/16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

実務では、ユーザー入力や外部データのように不正な値が入る可能性がある場合、TryParseExactが安全です。

1-3. TryParseExactを使うべきケースと使わなくてもよいケース

TryParseExactを使うべきケースは、入力される日付形式が決まっている場合です。

たとえば、次のようなケースです。

C#
// yyyyMMdd形式で固定
"20260616"

// yyyy-MM-dd HH:mm:ss形式で固定
"2026-06-16 09:30:00"

// APIの仕様でISO 8601形式が決まっている
"2026-06-16T09:30:00+09:00"

入力形式が決まっている場合は、TryParseExactを使うことで、想定外の形式を弾けます。

一方、ユーザーが自由に入力する日付を柔軟に受け付けたい場合は、TryParseの方が向いていることもあります。

C#
DateTime.TryParse("2026年6月16日", out DateTime date);

ただし、TryParseは環境やカルチャによって解釈が変わる可能性があります。業務システムで「必ずこの形式で入力させたい」という場合は、TryParseExactを使う方が安全です。

1-4. 戻り値boolとout DateTimeの基本動作

TryParseExactの戻り値はboolです。

変換に成功するとtrue、失敗するとfalseが返ります。変換結果はout DateTimeで受け取ります。

C#
string text = "2026/06/16";

if (DateTime.TryParseExact(
text,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine($"変換成功: {date}");
}
else
{
Console.WriteLine("変換失敗");
}

失敗した場合、outで受け取るDateTimeには既定値が入ります。DateTimeの既定値は0001/01/01 0:00:00です。

そのため、outの値だけを見て成功・失敗を判断するのではなく、必ず戻り値のboolで判定しましょう。

2. DateTime.TryParseExactの基本構文と引数の意味

2-1. 基本構文:String・format・provider・styles・out result

DateTime.TryParseExactの代表的な構文は次のとおりです。

C#
DateTime.TryParseExact(
string s,
string format,
IFormatProvider provider,
DateTimeStyles style,
out DateTime result
);

実際のコードでは、次のように書きます。

C#
bool success = DateTime.TryParseExact(
"2026/06/16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime result
);

それぞれの引数には、次の意味があります。

C#
// 第一引数: 変換したい文字列
"2026/06/16"

// 第二引数: 期待する日付書式
"yyyy/MM/dd"

// 第三引数: カルチャ情報
CultureInfo.InvariantCulture

// 第四引数: 変換時のオプション
DateTimeStyles.None

// 第五引数: 変換結果
out DateTime result

2-2. 第一引数:変換したい日付文字列

第一引数には、DateTimeに変換したい文字列を指定します。

C#
string input = "2026/06/16";

この文字列が、第二引数で指定したフォーマットと一致している必要があります。

C#
DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

inputnullや空文字の場合、基本的には変換に失敗してfalseが返ります。

C#
string input = "";

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

Console.WriteLine(success); // False

2-3. 第二引数:一致させる日付書式フォーマット

第二引数には、入力文字列と一致させる日付書式を指定します。

C#
"yyyy/MM/dd"

たとえば、入力が"2026/06/16"なら、書式は"yyyy/MM/dd"です。

C#
DateTime.TryParseExact(
"2026/06/16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

入力が"2026-06-16"なら、書式は"yyyy-MM-dd"です。

C#
DateTime.TryParseExact(
"2026-06-16",
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

入力が"20260616"なら、書式は"yyyyMMdd"です。

C#
DateTime.TryParseExact(
"20260616",
"yyyyMMdd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

区切り文字も含めて一致している必要がある点に注意してください。

2-4. 第三引数:CultureInfoとカルチャ指定

第三引数には、日付文字列を解釈するためのカルチャ情報を指定します。

よく使われるのはCultureInfo.InvariantCultureです。

C#
CultureInfo.InvariantCulture

InvariantCultureは、特定の国や地域に依存しないカルチャです。固定形式の日付文字列を扱う場合に向いています。

C#
DateTime.TryParseExact(
"2026-06-16",
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

日本語の曜日や月名、午前・午後などを扱う場合は、日本語カルチャを指定します。

C#
var culture = new CultureInfo("ja-JP");

bool success = DateTime.TryParseExact(
"2026年06月16日",
"yyyy年MM月dd日",
culture,
DateTimeStyles.None,
out DateTime date
);

英語の月名を扱う場合は、英語カルチャを指定します。

C#
var culture = new CultureInfo("en-US");

bool success = DateTime.TryParseExact(
"June 16, 2026",
"MMMM dd, yyyy",
culture,
DateTimeStyles.None,
out DateTime date
);

2-5. 第四引数:DateTimeStylesの指定方法

第四引数には、変換時の細かい動作を指定するDateTimeStylesを渡します。

基本的にはDateTimeStyles.Noneで問題ありません。

C#
DateTimeStyles.None

前後の空白を許可したい場合は、DateTimeStyles.AllowWhiteSpacesを指定できます。

C#
bool success = DateTime.TryParseExact(
" 2026/06/16 ",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.AllowWhiteSpaces,
out DateTime date
);

UTCとして扱いたい場合や、ローカル時刻として扱いたい場合には、AssumeUniversalAssumeLocalなどを使うことがあります。

C#
DateTimeStyles.AssumeUniversal
DateTimeStyles.AssumeLocal
DateTimeStyles.AdjustToUniversal

ただし、タイムゾーンやオフセットを厳密に扱いたい場合は、DateTimeではなくDateTimeOffsetを検討した方がよい場面もあります。

2-6. 第五引数:変換結果を受け取るout DateTime

第五引数には、変換結果を受け取るout DateTimeを指定します。

C#
out DateTime result

C# 7.0以降では、out varを使って簡潔に書くこともできます。

C#
if (DateTime.TryParseExact(
"2026/06/16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var date))
{
Console.WriteLine(date);
}

out varを使うと、事前に変数を宣言する必要がありません。

C#
if (DateTime.TryParseExact(input, "yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var result))
{
Console.WriteLine(result);
}

実務では、if文の中でTryParseExactを呼び出し、成功した場合だけ変換後の値を使う書き方がよく使われます。

3. C# TryParseExactの基本的な使い方

3-1. yyyy/MM/dd形式の日付文字列をDateTimeに変換する例

yyyy/MM/dd形式の文字列をDateTimeに変換する基本例です。

C#
using System;
using System.Globalization;

class Program
{
static void Main()
{
string input = "2026/06/16";

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

if (success)
{
Console.WriteLine($"変換成功: {date}");
}
else
{
Console.WriteLine("変換失敗");
}
}
}

この例では、入力文字列"2026/06/16"と書式"yyyy/MM/dd"が一致しているため、変換に成功します。

3-2. yyyy-MM-dd形式の日付文字列をDateTimeに変換する例

ハイフン区切りの日付文字列を変換する場合は、書式にもハイフンを指定します。

C#
string input = "2026-06-16";

bool success = DateTime.TryParseExact(
input,
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

Console.WriteLine(success); // True
Console.WriteLine(date);

"yyyy/MM/dd"ではなく"yyyy-MM-dd"を指定する点が重要です。

C#
// これは失敗する
DateTime.TryParseExact(
"2026-06-16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

TryParseExactでは、スラッシュとハイフンの違いも判定対象になります。

3-3. yyyyMMdd形式の数値風文字列をDateTimeに変換する例

"20260616"のように、区切り文字のない日付文字列も変換できます。

C#
string input = "20260616";

bool success = DateTime.TryParseExact(
input,
"yyyyMMdd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

if (success)
{
Console.WriteLine(date); // 2026/06/16 0:00:00
}

注意点として、入力は数値ではなく文字列として扱うのが基本です。

C#
string input = "20260616";

整数型で扱うと、先頭にゼロがある形式や固定長チェックが難しくなる場合があります。日付コードとして扱うなら、文字列のまま処理する方が安全です。

3-4. 日付と時刻を含む文字列を変換する例

日付だけでなく、時刻を含む文字列も変換できます。

C#
string input = "2026-06-16 09:30:45";

bool success = DateTime.TryParseExact(
input,
"yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

if (success)
{
Console.WriteLine(dateTime); // 2026/06/16 9:30:45
}

HHは24時間表記の時、mmは分、ssは秒を表します。

C#
"yyyy-MM-dd HH:mm:ss"

ここでMMmmを間違えると失敗や誤解の原因になります。

C#
// MM: 月
// mm: 分

3-5. 変換成功時と失敗時の処理をif文で分ける例

TryParseExactは戻り値がboolなので、if文で成功時と失敗時の処理を分けられます。

C#
string input = "2026/06/16";

if (DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine($"有効な日付です: {date:yyyy-MM-dd}");
}
else
{
Console.WriteLine("日付の形式が正しくありません。yyyy/MM/dd形式で入力してください。");
}

入力チェックでは、このように失敗時にユーザー向けのメッセージを返す実装がよく使われます。

C#
if (!DateTime.TryParseExact(input, "yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var date))
{
Console.WriteLine("日付は yyyy/MM/dd 形式で入力してください。");
return;
}

成功した場合だけ後続処理に進めることで、不正な日付によるエラーを防げます。

4. TryParseExactでよく使う書式指定子一覧

4-1. 年・月・日:yyyy・MM・ddの使い方

日付変換でよく使う書式指定子は、yyyyMMddです。

C#
yyyy // 4桁の年
MM // 2桁の月
dd // 2桁の日

例は次のとおりです。

C#
string input = "2026/06/16";

DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

MMは2桁の月です。"06"には一致しますが、"6"には一致しません。

C#
// 成功
"2026/06/16" + "yyyy/MM/dd"

// 失敗
"2026/6/16" + "yyyy/MM/dd"

1桁の月や日を許可したい場合は、Mdを使います。

C#
DateTime.TryParseExact(
"2026/6/16",
"yyyy/M/d",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

4-2. 時・分・秒:HH・mm・ssの使い方

時刻を扱う場合は、HHmmssを使います。

C#
HH // 24時間表記の時
mm // 分
ss // 秒

たとえば、次のような日時文字列を変換できます。

C#
string input = "2026-06-16 09:30:45";

DateTime.TryParseExact(
input,
"yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

HHは24時間表記なので、00から23までを扱います。

C#
"00:00:00"
"09:30:45"
"23:59:59"

24:00:00のような表記は通常のDateTime変換では失敗するため注意してください。

4-3. 12時間表記と24時間表記:hh・HH・ttの違い

HHは24時間表記、hhは12時間表記です。

C#
HH // 24時間表記
hh // 12時間表記
tt // AM/PM指定

24時間表記の例です。

C#
string input = "2026-06-16 21:30:00";

DateTime.TryParseExact(
input,
"yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

12時間表記でAM/PMを含む場合は、ttを使います。

C#
string input = "2026-06-16 09:30:00 PM";

DateTime.TryParseExact(
input,
"yyyy-MM-dd hh:mm:ss tt",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

この場合、09:30:00 PMは21時30分として解釈されます。

日本語の午前・午後を扱う場合は、日本語カルチャを使います。

C#
var culture = new CultureInfo("ja-JP");

DateTime.TryParseExact(
"2026-06-16 午後 09:30:00",
"yyyy-MM-dd tt hh:mm:ss",
culture,
DateTimeStyles.None,
out DateTime dateTime
);

4-4. 曜日や月名を扱う場合の書式指定

曜日や月名を扱う場合は、カルチャの指定が重要です。

曜日にはdddddddを使います。

C#
ddd  // 短い曜日名
dddd // 完全な曜日名

英語の曜日を含む例です。

C#
var culture = new CultureInfo("en-US");

bool success = DateTime.TryParseExact(
"Tuesday, June 16, 2026",
"dddd, MMMM dd, yyyy",
culture,
DateTimeStyles.None,
out DateTime date
);

月名にはMMMMMMMを使います。

C#
MMM  // 短い月名
MMMM // 完全な月名

日本語の曜日を含める場合は、ja-JPを指定します。

C#
var culture = new CultureInfo("ja-JP");

bool success = DateTime.TryParseExact(
"2026年06月16日火曜日",
"yyyy年MM月dd日dddd",
culture,
DateTimeStyles.None,
out DateTime date
);

曜日を含む場合、日付と曜日の整合性が取れていないと変換に失敗する可能性があります。曜日が不要なら、入力形式から曜日を除いた方が扱いやすいです。

4-5. ミリ秒や小数秒を扱うfff・FFFFFFFの使い方

ミリ秒を扱う場合は、fffを使います。

C#
fff // 3桁のミリ秒

例です。

C#
string input = "2026-06-16 09:30:45.123";

bool success = DateTime.TryParseExact(
input,
"yyyy-MM-dd HH:mm:ss.fff",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

小数秒の桁数が可変の場合は、Fを使います。

C#
FFFFFFF

fは指定した桁数が必要ですが、Fは末尾のゼロや不足桁を柔軟に扱いやすい指定です。

C#
DateTime.TryParseExact(
"2026-06-16 09:30:45.1",
"yyyy-MM-dd HH:mm:ss.FFFFFFF",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

ログやAPIでは、小数秒の桁数がデータによって変わることがあります。その場合は、複数フォーマットを指定する方法も有効です。

4-6. タイムゾーンやオフセットを扱うK・zzzの使い方

タイムゾーンやUTCオフセットを含む文字列では、Kzzzを使います。

C#
K   // タイムゾーン情報
zzz // +09:00 のようなオフセット

オフセットを含む例です。

C#
string input = "2026-06-16 09:30:00 +09:00";

bool success = DateTime.TryParseExact(
input,
"yyyy-MM-dd HH:mm:ss zzz",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

ISO 8601形式に近い文字列を扱う例です。

C#
string input = "2026-06-16T09:30:00+09:00";

bool success = DateTime.TryParseExact(
input,
"yyyy-MM-dd'T'HH:mm:sszzz",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

Tのような固定文字は、シングルクォートで囲むとリテラルとして扱えます。

C#
"yyyy-MM-dd'T'HH:mm:sszzz"

ただし、オフセット情報を保持したい場合は、DateTimeOffset.TryParseExactを使う方が適しています。

4-7. 大文字小文字を間違えやすい書式指定子の注意点

TryParseExactの書式指定子は、大文字小文字の違いが重要です。

特に間違えやすいのは、MMmmです。

C#
MM // 月
mm // 分

正しい例です。

C#
"yyyy-MM-dd HH:mm:ss"

間違った例です。

C#
"yyyy-mm-dd HH:MM:ss"

この場合、mmは月ではなく分、MMは分ではなく月を意味するため、意図した変換になりません。

また、C#のカスタム日付書式では、年には通常yyyyを使います。YYYYのような指定は意図通りに扱われないため避けましょう。

C#
// 推奨
"yyyy-MM-dd"

// 非推奨
"YYYY-MM-DD"

ddは日、DDは一般的な日付指定としては使いません。ほかの言語やライブラリの書式と混同しないようにしましょう。

5. TryParseExactで変換に失敗する主な原因

5-1. 日付文字列とformatが完全一致していない

TryParseExactで最も多い失敗原因は、入力文字列とフォーマットが完全一致していないことです。

C#
string input = "2026-06-16";

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

この例では、入力はハイフン区切りですが、フォーマットはスラッシュ区切りです。そのため失敗します。

正しくは次のように書きます。

C#
bool success = DateTime.TryParseExact(
"2026-06-16",
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

TryParseExactでは、年・月・日だけでなく、区切り文字、空白、時刻、AM/PM表記まで一致している必要があります。

5-2. yyyyとYYYYを混同している

C#で4桁の年を表す場合は、基本的にyyyyを使います。

C#
"yyyy-MM-dd"

ほかの言語やライブラリではYYYYを使う場面がありますが、C#のDateTime書式では混同しないようにしましょう。

C#
// 正しい
DateTime.TryParseExact(
"2026-06-16",
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

次のような書き方は避けるべきです。

C#
// 避ける
"YYYY-MM-DD"

C#では、日付の年・月・日を指定する場合、まずは次の形を基本にすると分かりやすいです。

C#
"yyyy/MM/dd"
"yyyy-MM-dd"
"yyyyMMdd"

5-3. MMとmmを間違えている

MMmmの間違いも非常によくあります。

C#
MM // 月
mm // 分

たとえば、次の指定は正しいです。

C#
"yyyy-MM-dd HH:mm:ss"

しかし、次のように書くと意味が変わります。

C#
"yyyy-mm-dd HH:MM:ss"

yyyy-mm-ddmmは月ではなく分です。HH:MM:ssMMは分ではなく月です。

正しい書式を整理すると、次のようになります。

C#
: yyyy
: MM
: dd
: HH
: mm
: ss

変換に失敗した場合は、まずMMmmを確認しましょう。

5-4. 区切り文字のスラッシュ・ハイフン・空白が一致していない

TryParseExactでは、区切り文字も一致している必要があります。

C#
// 入力
"2026/06/16"

// 書式
"yyyy-MM-dd"

この組み合わせは失敗します。

正しい組み合わせは次のとおりです。

C#
"2026/06/16"  -> "yyyy/MM/dd"
"2026-06-16" -> "yyyy-MM-dd"
"2026.06.16" -> "yyyy.MM.dd"
"20260616" -> "yyyyMMdd"

日付と時刻の間の空白も一致が必要です。

C#
// 入力に空白あり
"2026-06-16 09:30:00"

// 書式にも空白が必要
"yyyy-MM-dd HH:mm:ss"

入力が"2026-06-16T09:30:00"のようにTで区切られている場合は、書式にもTを入れます。

C#
"yyyy-MM-dd'T'HH:mm:ss"

5-5. 1桁の月日と2桁指定の不一致

MMddは2桁指定です。

C#
"yyyy/MM/dd"

そのため、次の入力は成功します。

C#
"2026/06/05"

しかし、次の入力は失敗します。

C#
"2026/6/5"

1桁の月日を許可したい場合は、Mdを使います。

C#
bool success = DateTime.TryParseExact(
"2026/6/5",
"yyyy/M/d",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

2桁と1桁の両方を許可したい場合は、複数フォーマットを指定します。

C#
string[] formats =
{
"yyyy/MM/dd",
"yyyy/M/d"
};

bool success = DateTime.TryParseExact(
"2026/6/5",
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

5-6. CultureInfoの指定が入力文字列と合っていない

曜日、月名、午前・午後などを扱う場合、CultureInfoが合っていないと失敗します。

たとえば、英語の月名を含む文字列には英語カルチャを指定します。

C#
var culture = new CultureInfo("en-US");

bool success = DateTime.TryParseExact(
"June 16, 2026",
"MMMM dd, yyyy",
culture,
DateTimeStyles.None,
out DateTime date
);

日本語の年月日を扱う場合は、日本語カルチャを指定します。

C#
var culture = new CultureInfo("ja-JP");

bool success = DateTime.TryParseExact(
"2026年06月16日",
"yyyy年MM月dd日",
culture,
DateTimeStyles.None,
out DateTime date
);

固定形式の数値日付だけを扱う場合は、CultureInfo.InvariantCultureが使いやすいです。

C#
CultureInfo.InvariantCulture

5-7. 存在しない日付を指定している

書式が正しくても、存在しない日付は変換できません。

C#
string input = "2026/02/30";

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

Console.WriteLine(success); // False

2月30日や、存在しない月、範囲外の時刻などは失敗します。

C#
"2026/13/01"     // 13月は存在しない
"2026/00/01" // 0月は存在しない
"2026/06/32" // 32日は存在しない
"2026-06-16 25:00:00" // 25時は通常の時刻として無効

TryParseExactは形式だけでなく、日付として有効かどうかも判定します。

5-8. 余分な空白や不可視文字が含まれている

入力文字列に余分な空白があると、変換に失敗することがあります。

C#
string input = " 2026/06/16 ";

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

Console.WriteLine(success); // Falseになる場合がある

対策として、事前にTrim()する方法があります。

C#
string input = " 2026/06/16 ";
input = input.Trim();

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

または、DateTimeStyles.AllowWhiteSpacesを指定します。

C#
bool success = DateTime.TryParseExact(
" 2026/06/16 ",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.AllowWhiteSpaces,
out DateTime date
);

CSVや外部ファイルでは、見た目では分かりにくい不可視文字が混ざることもあります。変換前に入力値を確認することが大切です。

5-9. AM/PMや午前・午後の表記がカルチャと合っていない

12時間表記を扱う場合は、ttとカルチャの組み合わせに注意が必要です。

英語のAM/PMを扱う例です。

C#
bool success = DateTime.TryParseExact(
"2026-06-16 09:30:00 PM",
"yyyy-MM-dd hh:mm:ss tt",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

日本語の午前・午後を扱う場合は、ja-JPを指定します。

C#
var culture = new CultureInfo("ja-JP");

bool success = DateTime.TryParseExact(
"2026-06-16 午後 09:30:00",
"yyyy-MM-dd tt hh:mm:ss",
culture,
DateTimeStyles.None,
out DateTime date
);

カルチャが合っていないと、AMPM午前午後を正しく解釈できず、変換に失敗することがあります。

6. 失敗しないための実践的な書き方

6-1. CultureInfo.InvariantCultureを使う基本方針

固定形式の日付文字列を扱う場合は、CultureInfo.InvariantCultureを使うのが基本です。

C#
DateTime.TryParseExact(
input,
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

InvariantCultureを使うことで、実行環境の地域設定に影響されにくくなります。

特に、CSV、ログ、API、ファイル名など、機械的に生成された日付文字列を扱う場合に向いています。

C#
"2026-06-16"
"20260616"
"2026-06-16T09:30:00"

一方で、日本語の曜日や英語の月名など、言語に依存する文字列を扱う場合は、適切なCultureInfoを指定しましょう。

6-2. DateTimeStyles.Noneを指定する場合

特別な変換ルールが不要な場合は、DateTimeStyles.Noneを指定します。

C#
DateTimeStyles.None

最も基本的な書き方です。

C#
bool success = DateTime.TryParseExact(
"2026/06/16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

まずはDateTimeStyles.Noneで実装し、空白やタイムゾーンなどの要件が出てきた場合に、必要なオプションを追加すると分かりやすいです。

6-3. AllowWhiteSpacesで前後の空白を許容する方法

入力値の前後や途中に空白が入る可能性がある場合は、DateTimeStyles.AllowWhiteSpacesを指定できます。

C#
bool success = DateTime.TryParseExact(
" 2026/06/16 ",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.AllowWhiteSpaces,
out DateTime date
);

フォーム入力やCSV取込では、前後に空白が入ることがあります。

C#
"2026/06/16 "
" 2026/06/16"
" 2026/06/16 "

このような入力を許容したい場合に便利です。

ただし、空白を許容しすぎると不正な入力に気づきにくくなることもあります。厳密にチェックしたい場合は、Trim()してから変換する方が意図を明確にできます。

6-4. AssumeLocal・AssumeUniversal・AdjustToUniversalの使い分け

日時文字列にタイムゾーン情報がない場合、DateTimeStyles.AssumeLocalAssumeUniversalを使って、ローカル時刻またはUTCとして解釈できます。

ローカル時刻として扱う例です。

C#
bool success = DateTime.TryParseExact(
"2026-06-16 09:30:00",
"yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out DateTime dateTime
);

UTCとして扱う例です。

C#
bool success = DateTime.TryParseExact(
"2026-06-16 09:30:00",
"yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal,
out DateTime dateTime
);

UTCに変換したい場合は、AdjustToUniversalを組み合わせることがあります。

C#
bool success = DateTime.TryParseExact(
"2026-06-16 09:30:00 +09:00",
"yyyy-MM-dd HH:mm:ss zzz",
CultureInfo.InvariantCulture,
DateTimeStyles.AdjustToUniversal,
out DateTime utcDateTime
);

ただし、オフセットを保持したい場合はDateTimeOffsetの方が適しています。DateTimeは時刻そのものを扱う型であり、オフセット情報を保持する用途には限界があります。

6-5. 入力値をTrimしてから変換する方法

外部から受け取る入力値は、変換前にTrim()しておくと安定します。

C#
string input = " 2026/06/16 ";
string trimmed = input.Trim();

bool success = DateTime.TryParseExact(
trimmed,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

nullの可能性がある場合は、null条件演算子を使うか、事前にチェックします。

C#
string? input = GetInput();

if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("日付が入力されていません。");
return;
}

if (DateTime.TryParseExact(
input.Trim(),
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine(date);
}
else
{
Console.WriteLine("日付形式が正しくありません。");
}

Trim()は前後の空白を削除しますが、文字列の途中にある不要な空白は削除しません。

C#
"2026 / 06 / 16"

このような入力を許可するかどうかは、仕様として決めておくとよいです。

6-6. 変換失敗時にエラーメッセージを出し分ける方法

TryParseExactは失敗理由までは返しません。失敗理由を出し分けたい場合は、事前チェックを組み合わせます。

C#
string input = "";

if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("日付を入力してください。");
}
else if (!DateTime.TryParseExact(
input.Trim(),
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine("日付は yyyy/MM/dd 形式で入力してください。");
}
else
{
Console.WriteLine($"入力された日付: {date:yyyy-MM-dd}");
}

存在しない日付と形式違いを厳密に分けたい場合は、正規表現などで形式を確認してから、TryParseExactで日付として有効かを確認する方法があります。

C#
using System.Text.RegularExpressions;

string input = "2026/02/30";

if (!Regex.IsMatch(input, @"^\d{4}/\d{2}/\d{2}$"))
{
Console.WriteLine("日付は yyyy/MM/dd 形式で入力してください。");
}
else if (!DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine("存在しない日付です。");
}
else
{
Console.WriteLine($"有効な日付です: {date:yyyy-MM-dd}");
}

このように、形式チェックと日付妥当性チェックを分けると、ユーザーに分かりやすいメッセージを返せます。

7. 複数の書式を許可するTryParseExactの使い方

7-1. string配列で複数フォーマットを指定する基本

TryParseExactでは、複数のフォーマットを配列で指定できます。

C#
string[] formats =
{
"yyyy/MM/dd",
"yyyy-MM-dd",
"yyyyMMdd"
};

bool success = DateTime.TryParseExact(
input,
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

この場合、入力文字列が配列内のいずれかの書式に一致すれば変換に成功します。

C#
"2026/06/16" // yyyy/MM/dd に一致
"2026-06-16" // yyyy-MM-dd に一致
"20260616" // yyyyMMdd に一致

ユーザー入力や外部データでは、複数の形式が混在することがあります。そのような場合に便利です。

7-2. yyyy/MM/ddとyyyy-MM-ddの両方を許可する例

スラッシュ区切りとハイフン区切りの両方を許可する例です。

C#
string input = "2026-06-16";

string[] formats =
{
"yyyy/MM/dd",
"yyyy-MM-dd"
};

bool success = DateTime.TryParseExact(
input,
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

if (success)
{
Console.WriteLine(date);
}
else
{
Console.WriteLine("日付形式が正しくありません。");
}

このコードでは、次のどちらも成功します。

C#
"2026/06/16"
"2026-06-16"

ただし、許可する形式が増えるほど、入力ルールが曖昧になります。業務要件として本当に複数形式を許可してよいか確認しましょう。

7-3. 日付のみ・日時ありの両方を許可する例

日付のみと、時刻付きの両方を許可することもできます。

C#
string[] formats =
{
"yyyy-MM-dd",
"yyyy-MM-dd HH:mm:ss"
};

string input = "2026-06-16 09:30:00";

bool success = DateTime.TryParseExact(
input,
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

if (success)
{
Console.WriteLine(dateTime);
}

この場合、次のどちらも成功します。

C#
"2026-06-16"
"2026-06-16 09:30:00"

日付のみの場合、時刻は00:00:00になります。

C#
2026-06-16 00:00:00

時刻が必須なのか任意なのかは、仕様として明確にしておきましょう。

7-4. ユーザー入力やCSV取込で複数書式を扱う実例

CSV取込では、データ作成元によって日付形式が混在することがあります。

C#
string[] formats =
{
"yyyy/MM/dd",
"yyyy-MM-dd",
"yyyyMMdd",
"yyyy-MM-dd HH:mm:ss"
};

foreach (var line in csvLines)
{
string dateText = line.DateText.Trim();

if (DateTime.TryParseExact(
dateText,
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine($"変換成功: {date:yyyy-MM-dd}");
}
else
{
Console.WriteLine($"日付変換失敗: {dateText}");
}
}

このように、複数形式を許可すると取込処理の柔軟性が上がります。

ただし、データ品質を保つためには、最終的にはシステム側で推奨形式を統一するのが望ましいです。

C#
// 保存時や出力時は統一する
string normalized = date.ToString("yyyy-MM-dd");

7-5. 複数書式を使う場合の注意点

複数書式を使う場合は、似た形式の解釈に注意が必要です。

たとえば、次のような形式を同時に許可すると、日付の意味が分かりにくくなることがあります。

C#
"MM/dd/yyyy"
"dd/MM/yyyy"

"01/02/2026"が1月2日なのか、2月1日なのか曖昧になります。

日本国内の業務システムでは、次のような形式に統一すると扱いやすいです。

C#
"yyyy/MM/dd"
"yyyy-MM-dd"
"yyyyMMdd"

複数形式を許可する場合でも、出力や保存時には1つの形式に正規化することをおすすめします。

C#
date.ToString("yyyy-MM-dd")

8. 実務で使えるTryParseExactのサンプル集

8-1. フォーム入力の日付チェック

フォームで入力された日付をチェックする例です。

C#
using System;
using System.Globalization;

public class DateValidator
{
public static bool IsValidDate(string? input, out DateTime date)
{
date = default;

if (string.IsNullOrWhiteSpace(input))
{
return false;
}

return DateTime.TryParseExact(
input.Trim(),
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out date
);
}
}

使い方は次のとおりです。

C#
string input = "2026/06/16";

if (DateValidator.IsValidDate(input, out DateTime date))
{
Console.WriteLine($"登録日: {date:yyyy-MM-dd}");
}
else
{
Console.WriteLine("日付は yyyy/MM/dd 形式で入力してください。");
}

入力チェックでは、null、空文字、空白だけの文字列も考慮しましょう。

8-2. CSVの日付列をDateTimeに変換する

CSVの日付列を変換する例です。

C#
using System;
using System.Globalization;

string[] rows =
{
"001,2026/06/16,田中",
"002,2026-06-17,佐藤",
"003,20260618,鈴木"
};

string[] formats =
{
"yyyy/MM/dd",
"yyyy-MM-dd",
"yyyyMMdd"
};

foreach (string row in rows)
{
string[] columns = row.Split(',');
string id = columns[0];
string dateText = columns[1].Trim();
string name = columns[2];

if (DateTime.TryParseExact(
dateText,
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine($"{id}: {name} - {date:yyyy-MM-dd}");
}
else
{
Console.WriteLine($"{id}: 日付変換失敗 - {dateText}");
}
}

CSV取込では、行番号や元の文字列をログに残しておくと、エラー調査がしやすくなります。

C#
Console.WriteLine($"日付変換失敗: 行={rowNumber}, 値={dateText}");

8-3. ログファイルの日時文字列を変換する

ログファイルでは、日時が固定形式で出力されることが多いです。

C#
string logDateText = "2026-06-16 09:30:45.123";

bool success = DateTime.TryParseExact(
logDateText,
"yyyy-MM-dd HH:mm:ss.fff",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime logDate
);

if (success)
{
Console.WriteLine($"ログ日時: {logDate:yyyy-MM-dd HH:mm:ss.fff}");
}

ログの先頭に日時が含まれる場合は、対象部分だけを切り出してから変換します。

C#
string logLine = "2026-06-16 09:30:45.123 INFO 処理を開始しました";

string datePart = logLine.Substring(0, 23);

if (DateTime.TryParseExact(
datePart,
"yyyy-MM-dd HH:mm:ss.fff",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine(date);
}

ログ形式が固定されている場合、TryParseExactは非常に相性がよいです。

8-4. APIレスポンスの日付文字列を変換する

APIレスポンスでは、ISO 8601形式の日時が返ってくることがあります。

C#
string apiDate = "2026-06-16T09:30:00+09:00";

bool success = DateTime.TryParseExact(
apiDate,
"yyyy-MM-dd'T'HH:mm:sszzz",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dateTime
);

if (success)
{
Console.WriteLine(dateTime);
}

ただし、APIの日付にオフセットが含まれている場合は、DateTimeOffsetの方が適していることがあります。

C#
bool success = DateTimeOffset.TryParseExact(
apiDate,
"yyyy-MM-dd'T'HH:mm:sszzz",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTimeOffset dateTimeOffset
);

APIの仕様で日付形式が決まっている場合は、その仕様に合わせてフォーマットを固定しましょう。

8-5. ファイル名に含まれる日付をDateTimeに変換する

ファイル名に日付が含まれるケースです。

C#
string fileName = "sales_20260616.csv";

string dateText = fileName
.Replace("sales_", "")
.Replace(".csv", "");

bool success = DateTime.TryParseExact(
dateText,
"yyyyMMdd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

if (success)
{
Console.WriteLine($"対象日: {date:yyyy-MM-dd}");
}

より安全に書くなら、正規表現で日付部分を抽出します。

C#
using System.Text.RegularExpressions;

string fileName = "sales_20260616.csv";

Match match = Regex.Match(fileName, @"sales_(\d{8})\.csv");

if (match.Success)
{
string dateText = match.Groups[1].Value;

if (DateTime.TryParseExact(
dateText,
"yyyyMMdd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine(date);
}
}

ファイル名の日付は固定長で扱えることが多いため、yyyyMMdd形式と相性がよいです。

8-6. nullable DateTimeとして扱う実装例

日付が任意入力の場合は、DateTime?として扱うと便利です。

C#
using System;
using System.Globalization;

public static DateTime? ToNullableDateTime(string? input)
{
if (string.IsNullOrWhiteSpace(input))
{
return null;
}

if (DateTime.TryParseExact(
input.Trim(),
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
return date;
}

return null;
}

使い方です。

C#
DateTime? date = ToNullableDateTime("2026/06/16");

if (date.HasValue)
{
Console.WriteLine(date.Value.ToString("yyyy-MM-dd"));
}
else
{
Console.WriteLine("日付なし、または変換失敗");
}

空欄を許可する入力項目では、変換失敗と未入力を区別したい場合もあります。その場合は、戻り値だけでなくエラー種別を返す設計にするとよいです。

9. ParseExact・TryParse・TryParseExactの使い分け

9-1. ParseExactは失敗時に例外が発生する

ParseExactは、指定した書式に一致する場合だけ変換しますが、失敗すると例外が発生します。

C#
DateTime date = DateTime.ParseExact(
"2026/06/16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture
);

不正な入力を渡すと、例外処理が必要になります。

C#
try
{
DateTime date = DateTime.ParseExact(
"2026-06-16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture
);
}
catch (FormatException)
{
Console.WriteLine("日付形式が正しくありません。");
}

入力値が必ず正しいと分かっている場合はParseExactでもよいですが、ユーザー入力や外部データにはTryParseExactの方が安全です。

9-2. TryParseは書式が厳密でない

TryParseは、日付として解釈できるかを柔軟に判定します。

C#
bool success = DateTime.TryParse("2026/06/16", out DateTime date);

ただし、柔軟である分、意図しない形式も受け入れてしまう可能性があります。

C#
DateTime.TryParse("6/16/2026", out DateTime date);

また、カルチャや実行環境によって解釈が変わることもあります。

業務システムで入力形式を固定したい場合は、TryParseよりTryParseExactが向いています。

9-3. TryParseExactは書式を厳密に指定できる

TryParseExactは、指定した書式に一致する場合だけ変換できます。

C#
bool success = DateTime.TryParseExact(
"2026/06/16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

次のように、形式が違えば失敗します。

C#
// 入力はハイフン、書式はスラッシュなので失敗
DateTime.TryParseExact(
"2026-06-16",
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

厳密な入力チェックをしたい場合に適しています。

9-4. 例外処理を避けたい場合はTryParseExactを使う

TryParseExactは、変換に失敗しても例外を投げません。

C#
if (DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
Console.WriteLine("変換成功");
}
else
{
Console.WriteLine("変換失敗");
}

大量データの取込処理では、1件ごとに例外を発生させるより、boolで判定した方が処理しやすいです。

C#
foreach (var item in items)
{
if (!DateTime.TryParseExact(item.DateText, "yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var date))
{
// エラーログに記録して次の行へ
continue;
}

// 正常処理
}

例外は本当に例外的な状況に使い、通常の入力チェックにはTryParseExactを使うのが実務では扱いやすいです。

9-5. 入力チェック・データ取込・API処理での選び方

入力チェックでは、TryParseExactを使うと安全です。

C#
// フォーム入力
"yyyy/MM/dd"

CSVやExcel取込など、外部データを扱う場合もTryParseExactが向いています。

C#
// CSV取込
"yyyy-MM-dd"
"yyyyMMdd"

API処理では、仕様で定義された日付形式に合わせてTryParseExactまたはDateTimeOffset.TryParseExactを使います。

C#
// APIレスポンス
"yyyy-MM-dd'T'HH:mm:sszzz"

一方、管理者が手作業で入力する簡易ツールなど、多少柔軟に日付を受け付けたい場合はTryParseでもよいことがあります。

使い分けの目安は次のとおりです。

C#
Parse         // 正しい入力が前提で、失敗時は例外でよい
TryParse // 柔軟に日付を解釈したい
ParseExact // 書式固定で、失敗時は例外でよい
TryParseExact // 書式固定で、失敗時に例外を避けたい

10. DateTimeOffset.TryParseExactとの違い

10-1. DateTimeとDateTimeOffsetの違い

DateTimeは日付と時刻を表す型です。

C#
DateTime dateTime = new DateTime(2026, 6, 16, 9, 30, 0);

一方、DateTimeOffsetは日付と時刻に加えて、UTCからのオフセットを保持できます。

C#
DateTimeOffset dateTimeOffset =
new DateTimeOffset(2026, 6, 16, 9, 30, 0, TimeSpan.FromHours(9));

たとえば、日本時間の2026-06-16 09:30:00 +09:00を扱う場合、DateTimeOffsetなら+09:00という情報も保持できます。

C#
2026-06-16 09:30:00 +09:00

DateTimeでは、オフセット情報を保持する用途には注意が必要です。

10-2. タイムゾーンやオフセットを保持したい場合

APIや外部システムでは、次のような日時文字列がよく使われます。

C#
"2026-06-16T09:30:00+09:00"
"2026-06-16T00:30:00Z"

このような文字列を扱う場合、オフセットを保持したいならDateTimeOffset.TryParseExactを使うのがおすすめです。

C#
string input = "2026-06-16T09:30:00+09:00";

bool success = DateTimeOffset.TryParseExact(
input,
"yyyy-MM-dd'T'HH:mm:sszzz",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTimeOffset result
);

if (success)
{
Console.WriteLine(result); // 2026-06-16 09:30:00 +09:00
Console.WriteLine(result.Offset); // 09:00:00
}

時刻の比較やUTC変換が必要なシステムでは、DateTimeOffsetを使うと意図が明確になります。

10-3. DateTimeOffset.TryParseExactを使うべきケース

DateTimeOffset.TryParseExactを使うべきケースは、オフセット情報が重要な場合です。

たとえば、次のような処理です。

C#
// APIレスポンスの日時
"2026-06-16T09:30:00+09:00"

// 海外ユーザーの操作日時
"2026-06-15T20:30:00-04:00"

// UTC時刻
"2026-06-16T00:30:00Z"

サンプルです。

C#
string input = "2026-06-16T00:30:00Z";

bool success = DateTimeOffset.TryParseExact(
input,
"yyyy-MM-dd'T'HH:mm:ssK",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTimeOffset dateTimeOffset
);

if (success)
{
Console.WriteLine(dateTimeOffset);
}

ログ、API、分散システム、海外対応サービスでは、DateTimeよりDateTimeOffsetの方が適切な場面が多いです。

10-4. DateTime.TryParseExactとの使い分け

日付だけを扱う場合や、タイムゾーンを意識しない業務日付ならDateTime.TryParseExactで十分です。

C#
"2026/06/16"
"2026-06-16"
"20260616"

一方、時刻とオフセットを含む場合はDateTimeOffset.TryParseExactを検討しましょう。

C#
"2026-06-16T09:30:00+09:00"

使い分けの目安は次のとおりです。

C#
DateTime.TryParseExact
// 日付、業務日、タイムゾーンを意識しない日時

DateTimeOffset.TryParseExact
// オフセット付き日時、API、ログ、海外対応

特に、外部システムと日時をやり取りする場合は、DateTimeOffsetを使うことで時差に関するトラブルを減らせます。

11. TryParseExactに関するよくある質問

11-1. TryParseExactでyyyyMMddが変換できないのはなぜ?

yyyyMMddが変換できない場合、入力文字列が8桁になっているか確認しましょう。

C#
// 成功
"20260616"

// 失敗
"2026616"

正しい例です。

C#
bool success = DateTime.TryParseExact(
"20260616",
"yyyyMMdd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

yyyyMMddでは、月と日が2桁である必要があります。

C#
2026年6月5日 -> "20260605"

"202665"のような形式はyyyyMMddには一致しません。

11-2. yyyy-MM-dd HH:mm:ssが失敗する原因は?

"yyyy-MM-dd HH:mm:ss"が失敗する主な原因は、入力文字列と書式が一致していないことです。

成功する例です。

C#
"2026-06-16 09:30:00"
"yyyy-MM-dd HH:mm:ss"

失敗する例です。

C#
"2026/06/16 09:30:00"  // 区切り文字が違う
"2026-06-16T09:30:00" // 日付と時刻の区切りがT
"2026-06-16 9:30:00" // 時が1桁
"2026-06-16 09:30" // 秒がない

入力に合わせて書式を変更します。

C#
"2026-06-16T09:30:00" -> "yyyy-MM-dd'T'HH:mm:ss"
"2026-06-16 9:30:00" -> "yyyy-MM-dd H:mm:ss"
"2026-06-16 09:30" -> "yyyy-MM-dd HH:mm"

11-3. 1桁の月や日を変換するには?

1桁の月や日を変換するには、Mdを使います。

C#
bool success = DateTime.TryParseExact(
"2026/6/5",
"yyyy/M/d",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

2桁の月日ならMMddを使います。

C#
"2026/06/05" -> "yyyy/MM/dd"

両方許可したい場合は、複数フォーマットを指定します。

C#
string[] formats =
{
"yyyy/MM/dd",
"yyyy/M/d"
};

bool success = DateTime.TryParseExact(
"2026/6/5",
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

11-4. 日本語の年月日形式を変換するには?

日本語の年月日形式は、書式にを含めます。

C#
bool success = DateTime.TryParseExact(
"2026年06月16日",
"yyyy年MM月dd日",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

日本語の曜日や午前・午後を含む場合は、ja-JPを指定します。

C#
var culture = new CultureInfo("ja-JP");

bool success = DateTime.TryParseExact(
"2026年06月16日 火曜日",
"yyyy年MM月dd日 dddd",
culture,
DateTimeStyles.None,
out DateTime date
);

午前・午後を含む例です。

C#
var culture = new CultureInfo("ja-JP");

bool success = DateTime.TryParseExact(
"2026年06月16日 午後 09時30分",
"yyyy年MM月dd日 tt hh時mm分",
culture,
DateTimeStyles.None,
out DateTime date
);

11-5. nullや空文字を渡すとどうなる?

TryParseExactnullや空文字を渡すと、基本的には変換に失敗してfalseが返ります。

C#
string? input = null;

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

Console.WriteLine(success); // False

空文字も失敗します。

C#
string input = "";

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

Console.WriteLine(success); // False

実務では、先にstring.IsNullOrWhiteSpaceでチェックすると分かりやすいです。

C#
if (string.IsNullOrWhiteSpace(input))
{
Console.WriteLine("日付が入力されていません。");
return;
}

11-6. out varは使える?

TryParseExactではout varを使えます。

C#
if (DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var date))
{
Console.WriteLine(date);
}

out varを使うと、事前にDateTime date;と宣言する必要がありません。

従来の書き方です。

C#
DateTime date;

bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out date
);

現在のC#では、if文の中でout varを使う書き方が簡潔でよく使われます。

11-7. DateTimeStylesは何を指定すればよい?

特別な要件がなければ、まずはDateTimeStyles.Noneで問題ありません。

C#
DateTimeStyles.None

前後の空白を許可したい場合は、AllowWhiteSpacesを使います。

C#
DateTimeStyles.AllowWhiteSpaces

タイムゾーンやUTC変換を扱う場合は、次のような指定を検討します。

C#
DateTimeStyles.AssumeLocal
DateTimeStyles.AssumeUniversal
DateTimeStyles.AdjustToUniversal

ただし、オフセット付き日時を正確に扱いたい場合は、DateTimeOffset.TryParseExactも検討しましょう。

基本方針としては、次のように考えると分かりやすいです。

C#
固定の日付形式を厳密に変換する       -> DateTimeStyles.None
前後の空白を許可したい -> AllowWhiteSpaces
UTCとして扱いたい -> AssumeUniversal
UTCへ変換したい -> AdjustToUniversal
オフセットを保持したい -> DateTimeOffset.TryParseExact

まとめ

C#のTryParseExactは、文字列の日付を指定した書式どおりにDateTimeへ変換するためのメソッドです。

TryParseよりも厳密に書式をチェックでき、ParseExactのように失敗時に例外が発生しないため、ユーザー入力、CSV取込、ログ解析、API処理などで使いやすいのが特徴です。

基本形は次のとおりです。

C#
bool success = DateTime.TryParseExact(
input,
"yyyy/MM/dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

TryParseExactで失敗する場合は、まず次の点を確認しましょう。

C#
入力文字列とformatが一致しているか
yyyyを正しく使っているか
MMとmmを間違えていないか
区切り文字が一致しているか
1桁・2桁の指定が合っているか
CultureInfoが入力文字列に合っているか
存在しない日付ではないか
余分な空白が入っていないか

複数の形式を許可したい場合は、フォーマットを配列で指定できます。

C#
string[] formats =
{
"yyyy/MM/dd",
"yyyy-MM-dd",
"yyyyMMdd"
};

bool success = DateTime.TryParseExact(
input,
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date
);

タイムゾーンやオフセットを保持したい場合は、DateTime.TryParseExactではなくDateTimeOffset.TryParseExactを検討しましょう。

TryParseExactを正しく使えば、日付変換の失敗原因を減らし、入力チェックやデータ取込処理を安全に実装できます。