1. 日付のフォーマット
2025-06-19T17:30:00みたいな出力がカッコいいと思っても、おばあちゃんや経理さんに見せたら「もっとシンプルなのがいい」って言われるかも。たとえば19.06.2025 17:30みたいなやつね。英語圏の同僚は06/19/2025 5:30 PMを期待してるし、DevOpsやマシンは2025-06-19T17:30:00Zが好き。だから、プログラムのメモリ上のDateTimeは、画面上で何十通りものフォーマットで表示できるんだ。
逆のパターンもよくあるよ。ユーザーが入力欄に日付を入れる("19.06.2025"とか)とき、それをC#のオブジェクトにちゃんと変換して、日と月を間違えないようにしないとね。自動化や連携、レポート作成でも、テキストの日付を正しく解釈するのが大事だよ。
基本のフォーマット
C#では、日付や時間のオブジェクト(DateTime、DateOnly、TimeOnly、DateTimeOffset)を.ToString()メソッドで文字列に変換できるよ:
DateTime now = DateTime.Now;
Console.WriteLine(now.ToString()); // 出力: 19.06.2025 17:30:25
.ToString()をパラメータなしで呼ぶと、システムの現在のカルチャーに合わせたフォーマットになるよ(たとえばドイツ語Windowsなら一つのフォーマット、アメリカ英語なら別のフォーマット)。
標準フォーマット文字列
日付や時間の出力フォーマットを、いわゆる標準フォーマット文字列で明示的に指定できるよ:
| フォーマット | 説明 | 出力例 |
|---|---|---|
|
短い日付 | 19.06.2025 |
|
フル日付 | 2025年6月19日 |
|
フル日付+短い時間 | 2025年6月19日 17:30 |
|
フル日付+フル時間 | 2025年6月19日 17:30:25 |
|
短い日付と時間 | 19.06.2025 17:30 |
|
短い日付+フル時間 | 19.06.2025 17:30:25 |
|
短い時間 | 17:30 |
|
フル時間 | 17:30:25 |
|
月と日 | 6月19日 |
|
年と月 | 2025年6月 |
|
ISO 8601(ラウンドトリップ) | 2025-06-19T17:30:25.0000000 |
Console.WriteLine(now.ToString("d")); // 19.06.2025
Console.WriteLine(now.ToString("F")); // 2025年6月19日 17:30:25
Console.WriteLine(now.ToString("O")); // 2025-06-19T17:30:25.0000000
カスタム(ユーザー定義)テンプレート
もっと細かいフォーマットが必要なら、自分でテンプレートを作れるよ:
| 記号 | 意味 |
|---|---|
| yyyy | 年(4桁) |
| yy | 年(2桁) |
| MM | 月(2桁) |
| MMMM | 月の名前 |
| dd | 日(2桁) |
| d | 日(1~2桁) |
| HH | 時(24時間) |
| mm | 分 |
| ss | 秒 |
| tt | AM/PM |
Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm")); // 2025-06-19 17:30
Console.WriteLine(now.ToString("dd.MM.yyyy")); // 19.06.2025
Console.WriteLine(now.ToString("dddd, MMMM d")); // 水曜日, 6月 19
カルチャーごとのフォーマットの違い
他の国や言語っぽいフォーマットにしたいなら、ToString(string, IFormatProvider)のオーバーロードを使おう:
var enUS = new System.Globalization.CultureInfo("en-US");
Console.WriteLine(now.ToString("D", enUS)); // June 19, 2025
- "MM/dd/yyyy"みたいにテンプレートをガチ指定すれば、カルチャーに関係なく"06/19/2025"になるよ。
- でも"d"や"D"だけだと、カルチャーによってフォーマットが変わるから注意!
フォーマット作業の注意ポイント
日付フォーマットを扱うときは、標準フォーマットとカスタムフォーマットの違いをちゃんと理解しよう。標準フォーマット("d"、"F"、"G"など)はシステムのカルチャーに自動で合わせてくれるからUIには便利だけど、システム間のデータ交換ではトラブルの元になることも。カスタムフォーマットなら出力を完全にコントロールできるけど、細かい設定が必要だよ。
特に"O"(または"o")フォーマットは要チェック。これは「ラウンドトリップ」フォーマットで、文字列に変換してまたオブジェクトに戻しても、値が絶対に変わらないって保証してくれる。データのシリアライズやネットワーク越しのやりとりで超重要だよ。
2. 日付と時間のパース:文字列からオブジェクトへ
一番シンプルなパース:DateTime.Parse
DateTime.Parseは、システムのカルチャーを考慮して日付文字列を解釈してくれるメソッドだよ。
string input = "19.06.2025";
DateTime parsed = DateTime.Parse(input);
Console.WriteLine(parsed); // 19.06.2025 00:00:00
もし文字列が変だったら、プログラムは例外で落ちるから(誰でもやらかす!)注意してね。
カルチャーの指定
string input = "06/19/2025";
var enUS = new System.Globalization.CultureInfo("en-US");
DateTime dt = DateTime.Parse(input, enUS);
Console.WriteLine(dt); // 19.06.2025 00:00:00
安全なパース:TryParse
string input = "まちがった日付";
bool ok = DateTime.TryParse(input, out DateTime safeDate);
if (!ok)
Console.WriteLine("エラー: 日付の認識に失敗したよ!");
フォーマットをガチ指定:ParseExactとTryParseExact
var culture = System.Globalization.CultureInfo.InvariantCulture;
string dateStr = "2025-06-19";
DateTime d = DateTime.ParseExact(dateStr, "yyyy-MM-dd", culture);
Console.WriteLine(d); // 19.06.2025 00:00:00
bool parsedOk = DateTime.TryParseExact(
"19.06.2025",
"dd.MM.yyyy",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out DateTime myDate);
よく使うフォーマットの表
| 文字列 | フォーマット | 最終オブジェクト |
|---|---|---|
| "2025-06-19" | "yyyy-MM-dd" | 2025年6月19日 |
| "19.06.2025" | "dd.MM.yyyy" | 2025年6月19日 |
| "06/19/2025" | "MM/dd/yyyy" | 2025年6月19日 |
| "2025-06-19T14:15:16" | "s" | 2025年6月19日 14:15:16 |
DateTimeStylesの使い方
パース時にDateTimeStylesパラメータで動作を細かく制御できるよ。このenumで、パーサーが入力データをどう解釈するか決められる。たとえばDateTimeStyles.AssumeUniversalは、オフセットが明示されてない場合にUTCとして扱う。DateTimeStyles.AllowWhiteSpacesは、余計なスペースを無視してくれる。外部データを扱うとき、フォーマットが予測できない場合に便利だよ。
3. DateOnlyとTimeOnlyのフォーマットとパース
最近はDateOnlyやTimeOnlyみたいな新しい型が、余計な情報なしで日付や時間を保存するのによく使われてるよ。
フォーマット
DateOnly birthday = new DateOnly(2000, 6, 19);
Console.WriteLine(birthday.ToString("dd MMMM yyyy")); // 2000年6月19日
パース
var d = DateOnly.ParseExact("19.06.2000", "dd.MM.yyyy");
Console.WriteLine(d.Day); // 19
TimeOnly用のメソッドも同じ感じ(テンプレートは時・分・秒だけだけどね):
TimeOnly t = TimeOnly.ParseExact("23:59", "HH:mm");
Console.WriteLine(t.Hour); // 23
DateOnlyとTimeOnlyのメリット
DateOnlyやTimeOnlyをDateTimeの代わりに使うと、いくつか大きなメリットがあるよ。まず、意味がハッキリする。たとえば誕生日みたいに時間がいらない場合、DateOnlyを使えば意図が明確。次に、DateTimeでありがちなタイムゾーンの問題を避けられる。そして、これらの型はメモリやDBで場所も少なくて済むんだ。
タイムゾーンを考慮したフォーマットとパース
オフセット付きで時間を保存したいなら、DateTimeOffsetを使おう。これは国際化や分散システムで特に重要。フォーマットやパースのやり方は同じだけど、オフセットも管理できるよ:
DateTimeOffset meeting = new DateTimeOffset(2025, 6, 19, 17, 30, 0, TimeSpan.FromHours(3));
Console.WriteLine(meeting.ToString("o")); // 2025-06-19T17:30:00.0000000+03:00
string input = "2025-06-19T17:30:00+03:00";
var parsedOffset = DateTimeOffset.Parse(input);
Console.WriteLine(parsedOffset.Offset); // 03:00:00
4. 実践的な注意点とよくあるミス
ありがちな落とし穴は、国際フォーマットのパースで「日」と「月」を間違えること。たとえば"01/02/2025"はアメリカだと1月2日じゃなくて2月1日、ヨーロッパだと1月2日(びっくり!)。
それから、カルチャーの影響を忘れがち。たとえばアプリがドイツのサーバーで動いてて、ユーザーは色んな国からアクセスしてる場合、DBの日付フォーマットがサーバーごとに違って解釈されることもあるよ。
よくあるミスは、ログやデータ交換ファイルで.ToString()をカルチャーやフォーマット指定なしで使っちゃうこと。OSを変えたり、Windowsのユーザーを変えたりすると、結果が変わっちゃうかも。
日付操作のおすすめ
- 内部保存やデータ交換には、必ずインバリアントカルチャー(CultureInfo.InvariantCulture)や明示的なフォーマットを使おう。
- UIにはユーザーのカルチャーを使うか、好みのフォーマットを選ばせてあげよう。
- APIやDBでは、国際標準のISO 8601フォーマットを優先しよう。
- 入力データは必ずバリデーションしよう。日付の存在や範囲、値の妥当性をチェック!
いろんなデータソースとのやりとり
外部システムと連携するときは、いろんなフォーマットの日付を扱うことが多いよ。Unix timestamp(1970年1月1日からの秒数)で送ってくるシステムもあれば、各国のフォーマットの文字列で送ってくる場合も。事前にデータ交換フォーマットを決めて、パースの正しさを必ずチェックしよう。
それから、あいまいなフォーマットもあるから注意。たとえば"12/13/2025"は確実に2025年12月13日だけど、"12/11/2025"はカルチャーによって11月12日か12月11日になる。こういう場合は、あいまいじゃないフォーマットを使うか、パース時にカルチャーを明示しよう。
GO TO FULL VERSION