DateTime.Parse() / DateTime.TryParse()
| 対応: | C# 1.0(2002) |
|---|
日時を表す文字列を『DateTime』型に変換する『DateTime.Parse()』と、変換失敗時でも例外を投げない安全な『DateTime.TryParse()』です。
構文
// 文字列を DateTime に変換します(失敗すると例外が発生します)。 DateTime dt = DateTime.Parse(string s); // 変換を試みて、成功なら true・失敗なら false を返します(例外なし)。 bool ok = DateTime.TryParse(string s, out DateTime result); // 書式を指定して変換します。 DateTime dt = DateTime.ParseExact(string s, string format, IFormatProvider provider); bool ok = DateTime.TryParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result);
メソッド一覧
| メソッド | 概要 |
|---|---|
| DateTime.Parse(s) | 文字列を DateTime に変換します。変換できない場合は FormatException をスローします。 |
| DateTime.TryParse(s, out result) | 変換に成功すると true と result に変換結果を返します。失敗時は false を返し例外は発生しません。 |
| DateTime.ParseExact(s, format, provider) | 指定した書式に厳密に一致する場合のみ変換します。 |
| DateTime.TryParseExact(s, format, provider, style, out result) | ParseExact の例外なしバージョンです。 |
サンプルコード
Program.cs
using System;
using System.Globalization;
// DateTime.Parse() で変換します。
DateTime dt1 = DateTime.Parse("2024/01/15");
Console.WriteLine(dt1); // 2024/01/15 0:00:00
DateTime dt2 = DateTime.Parse("2024-03-20 14:30:00");
Console.WriteLine(dt2); // 2024/03/20 14:30:00
// TryParse() で安全に変換します(ユーザー入力などに使われます)。
string input = "2024/06/01";
if (DateTime.TryParse(input, out DateTime result))
{
Console.WriteLine($"変換成功: {result:yyyy年M月d日}");
}
else
{
Console.WriteLine("変換に失敗しました。");
}
// 変換できない文字列は false が返ります。
bool ok = DateTime.TryParse("abc", out DateTime failResult);
Console.WriteLine($"変換成功: {ok}"); // False
// ParseExact() で書式を厳密に指定します。
DateTime dt3 = DateTime.ParseExact("20240115", "yyyyMMdd", CultureInfo.InvariantCulture);
Console.WriteLine(dt3); // 2024/01/15 0:00:00
// TryParseExact() の例です。
bool parseOk = DateTime.TryParseExact(
"15-01-2024",
"dd-MM-yyyy",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime dt4
);
Console.WriteLine($"変換成功: {parseOk}, 結果: {dt4:yyyy/MM/dd}");
コンパイルして実行すると次のようになります。
dotnet script datetime_parse_tryparse.csx 2024/01/15 0:00:00 2024/03/20 14:30:00 変換成功: 2024年6月1日 変換成功: False 2024/01/15 0:00:00 変換成功: True, 結果: 2024/01/15
実践パターン: フォーム入力の安全な変換
ユーザーが入力した日付文字列は形式が不定なため、TryParse を使ってエラー処理と組み合わせます。
FormInputParse.cs
using System;
using System.Globalization;
// ユーザー入力の日付をパースするメソッドです。
static bool TryParseDate(string input, out DateTime date)
{
// 複数の書式を試みます。
string[] formats = { "yyyy/MM/dd", "yyyy-MM-dd", "yyyyMMdd", "MM/dd/yyyy" };
return DateTime.TryParseExact(
input,
formats,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out date
);
}
// テスト: Okabe Rintaro の活動記録日付
string[] inputs = { "2024/01/15", "2024-03-20", "20240601", "invalid" };
foreach (string s in inputs)
{
if (TryParseDate(s, out DateTime parsed))
Console.WriteLine($"[OK] {s} → {parsed:yyyy年M月d日}");
else
Console.WriteLine($"[NG] {s} → 変換失敗");
}
コンパイルして実行すると次のようになります。
dotnet script form_input_parse.csx [OK] 2024/01/15 → 2024年1月15日 [OK] 2024-03-20 → 2024年3月20日 [OK] 20240601 → 2024年6月1日 [NG] invalid → 変換失敗
実践パターン: ファイル名の日付をパース
ログファイルなど決まった書式のファイル名から日付を取り出すパターンです。書式が確定している場合は ParseExact が適しています。
FileNameParse.cs
using System;
using System.Globalization;
// ログファイル名(例: log_20240115.txt)から日付を取り出します。
string[] fileNames = { "log_20240115.txt", "log_20240316.txt", "log_20241231.txt" };
foreach (string fileName in fileNames)
{
// ファイル名から日付部分(8桁)を取り出します。
string datePart = fileName.Replace("log_", "").Replace(".txt", "");
DateTime fileDate = DateTime.ParseExact(datePart, "yyyyMMdd", CultureInfo.InvariantCulture);
// 30日以上前かどうかを判定します。
TimeSpan diff = DateTime.Today - fileDate;
bool isOld = diff.TotalDays >= 30;
Console.WriteLine($"{fileName}: {fileDate:yyyy/MM/dd} → {(isOld ? "削除対象" : "保持")}");
}
コンパイルして実行すると次のようになります。
dotnet script filename_parse.csx log_20240115.txt: 2024/01/15 → 削除対象 log_20240316.txt: 2024/03/16 → 削除対象 log_20241231.txt: 2024/12/31 → 保持
よくあるミス
よくあるミス1: Parse() で例外が発生する
『DateTime.Parse()』はパースに失敗すると FormatException をスローします。ユーザー入力や外部データには TryParse を使います。
using System; // NG: ユーザー入力に Parse() を使うと例外が発生する可能性があります。 string userInput = "令和6年1月15日"; // 非対応の形式 DateTime dt = DateTime.Parse(userInput); // FormatException がスローされます。
修正後は次の通りです。
dotnet run Unhandled exception. System.FormatException: String '令和6年1月15日' was not recognized as a valid DateTime.
修正後は次の通りです。
using System;
// OK: TryParse() を使えば例外なしに失敗を処理できます。
string userInput = "令和6年1月15日";
if (DateTime.TryParse(userInput, out DateTime dt))
Console.WriteLine($"変換成功: {dt}");
else
Console.WriteLine("変換に失敗しました。入力形式を確認してください。");
修正後は次の通りです。
dotnet run 変換に失敗しました。入力形式を確認してください。
よくあるミス2: CultureInfo の指定漏れ
ParseExact は CultureInfo を省略すると現在のカルチャに依存します。月の英語名("Jan" など)を含む書式は CultureInfo.InvariantCulture を指定しないとパースに失敗することがあります。
using System;
using System.Globalization;
// NG: 日本語環境では "Jan" を月名として認識できない場合があります。
// DateTime.ParseExact("15-Jan-2024", "dd-MMM-yyyy", null);
// OK: CultureInfo.InvariantCulture を指定します。
DateTime dt = DateTime.ParseExact(
"15-Jan-2024",
"dd-MMM-yyyy",
CultureInfo.InvariantCulture
);
Console.WriteLine(dt); // 2024/01/15 0:00:00
修正後は次の通りです。
dotnet run 2024/01/15 0:00:00
概要
ユーザーの入力値やファイルから読み込んだ文字列を DateTime に変換する際は、例外が発生しない『TryParse()』または『TryParseExact()』を使います。『Parse()』は形式が保証された文字列(定数や DB 値など)にのみ使います。
書式が特定の形式に固定されている場合(yyyyMMdd 形式のファイル名など)は『ParseExact()』が便利です。CultureInfo.InvariantCulture を指定するとロケールに依存しない変換が行えます。
変換後の日時書式化は『日時.ToString() / 日時.AddDays()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。