動くコード図鑑技術記事現場の渡り方キャリア論すべての記事About
技術記事

C# DateTime のフォーマット完全早見表 — yyyy/MM/dd・ファイル名・ログ出力でそのまま使うコピペ集

バイブス父さん
現役の業務SE
2026年7月3日13 min read
C# DateTime のフォーマット完全早見表 — yyyy/MM/dd・ファイル名・ログ出力でそのまま使うコピペ集

みなさんこんにちは!ヒロポンです!

画面の日付表示を直してる途中とか、夜間バッチのログファイル名にタイムスタンプ付けてる最中。ふっと手が止まること、ないですか??

「あれ、yyyy/MM/dd ってどう書くんやったっけ」。

ファイル名に付ける yyyyMMdd_HHmmss の大文字小文字、どっちが分やったっけ。俺もこれ、何回ググったか分からん。

この記事は、C# DateTime フォーマットの書き方を「画面表示」「ファイル名」「ログ」「SQL 渡し」の用途別に、そのままコピペで動く形でまとめた早見表です。

書式指定子そのものの意味も一覧にしてあります。ブックマークして、必要な行だけ持っていってください。

結論: 用途別にこの4行をコピペすればいい

先に答えだけ置いときます。DateTime の変数を now とすると、こう。

using System;
using System.Globalization;

class Program
{
    static void Main()
    {
        var now = new DateTime(2026, 6, 30, 14, 5, 9, 123);

        // 画面表示用: 2026/06/30
        Console.WriteLine(now.ToString("yyyy/MM/dd"));

        // ファイル名用: 20260630_140509
        Console.WriteLine(now.ToString("yyyyMMdd_HHmmss"));

        // ログ用: 2026-06-30 14:05:09.123
        Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm:ss.fff"));

        // SQL / API 渡し用 (ISO 8601): 2026-06-30T14:05:09
        Console.WriteLine(now.ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture));
    }
}

出力はこんな感じになります。

2026/06/30
20260630_140509
2026-06-30 14:05:09.123
2026-06-30T14:05:09

実行結果(.NET 9 で実機確認):

4用途のフォーマット出力の実行結果(画面・ファイル名・ログ・ISO 8601)

とりあえずこの4行で、業務でぶつかる日付整形の8割はカタがつきます。

残りの2割。書式指定子の意味、大文字小文字の罠、環境依存。ここを以下で潰していきます。

なぜ DateTime のフォーマットでこんなに迷うのか

理由はシンプルです。ToString に渡す書式文字列が、大文字と小文字で別物だから。

M は月、m は分。H は24時間、h は12時間。s は秒、f はミリ秒。

英語の頭文字で覚えればええんやけど、ここに落とし穴があって。MM(月)と mm(分)がぱっと見そっくりなんですよね。しかも両方とも「画面に2桁で出したい」場面で使う。だから取り違える。

で、タチが悪いのが、たいていの場合は動いてしまうこと。エラーにならず、ただ値だけ間違って出る。

しくみが分かれば怖くない。まず用途別のコピペ、次に指定子の意味、最後にハマりどころ、の順で見ていきます。

用途別コピペ早見表(画面・ファイル名・ログ・SQL 渡し)

業務でよく使う4用途を、選び方ごとに整理するとこうなります。

日付フォーマット4種(yyyy/MM/dd・yyyyMMdd_HHmmss・yyyy-MM-dd HH:mm:ss.fff・o)を画面表示/ファイル名/ログ/データ連携の用途別に比較した表

選んだら、あとは下のコピペを貼るだけ。

画面表示・帳票(人が読む)

人が見る場所はスラッシュ区切りが読みやすい。

dt.ToString("yyyy/MM/dd");           // 2026/06/30
dt.ToString("yyyy/MM/dd HH:mm");     // 2026/06/30 14:05
dt.ToString("yyyy年M月d日(ddd)");    // 2026年6月30日(火)

ddd で曜日が出ます。納品書とか帳票で「(火)」を添えたい時に便利。

ファイル名・キー(記号が使えない場所)

ファイル名には /: が使えない。だから区切りを抜いて、アンダースコアでつなぐ。

$"log_{dt:yyyyMMdd_HHmmss}.txt";     // log_20260630_140509.txt
$"backup_{dt:yyyyMMdd}.zip";         // backup_20260630.zip

文字列補間($"...")の中で {dt:書式} と書けるのも覚えとくと楽です。いい感じに短く書けます!!

ログ出力(機械が突合する)

ログは秒・ミリ秒まで欲しい。後でエラーの前後関係を追う時、ミリ秒があるとガチで助かります。

dt.ToString("yyyy-MM-dd HH:mm:ss.fff");   // 2026-06-30 14:05:09.123

ハイフン区切り+ゼロ埋めだと、文字列のままソートしても時系列に並ぶ。これが地味に効くんですよね。

SQL / API 渡し(システム間連携)

別システムやDBに渡すなら、人間の見やすさより機械が一意に解釈できることが正義。ISO 8601 一択です。

// オフセット不要なら DateTime のまま秒まで
dt.ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture);
// 2026-06-30T14:05:09

// 時差(オフセット)まで含めたいなら DateTimeOffset を使う
var dto = new DateTimeOffset(2026, 6, 30, 14, 5, 9, TimeSpan.FromHours(9));
dto.ToString("o");   // 2026-06-30T14:05:09.0000000+09:00

"o"(ラウンドトリップ書式)はミリ秒もオフセットも入る形式。

ひとつ注意。DateTime 単体だと Kind 次第で末尾のオフセットが付きません(Unspecified だと付かない)。時差をまたぐ連携なら、DateTimeOffset で持つのが確実です。

書式指定子そのものの早見表

「画面に出したい形が上のどれとも違う」時のために、部品の意味も置いときます。基準は 2026-06-30 14:05:09.123(火曜・JST) です。

カスタム書式指定子(自分で組み立てる用)

指定子 意味 出力例
yyyy 年4桁 2026
yy 年2桁 26
MM 月2桁(ゼロ埋め) 06
M 月(ゼロ埋めなし) 6
dd 日2桁(ゼロ埋め) 30
d 日(ゼロ埋めなし) 30
HH 時(24時間・2桁) 14
hh 時(12時間・2桁) 02
mm 分2桁 05
ss 秒2桁 09
fff ミリ秒3桁 123
tt 午前/午後 午後
ddd 曜日(短縮)
dddd 曜日(フル) 火曜日
zzz UTCオフセット +09:00

H(大文字)が24時間、h(小文字)が12時間。12時間表記なら tt で午前/午後を添えないと、14時なのか2時なのか分からなくなります。

標準書式指定子(1文字で済ませる用)

毎回 yyyy/MM/dd と書くのが面倒なら、1文字の標準書式もあります。

書式 用途 ja-JP の出力例
"d" 短い日付 2026/06/30
"D" 長い日付 2026年6月30日火曜日
"g" 一般(短) 2026/06/30 14:05
"G" 一般(長) 2026/06/30 14:05:09
"s" ソート可能 2026-06-30T14:05:09
"o" ラウンドトリップ 2026-06-30T14:05:09.1230000(Local時は末尾に +09:00)

ただし標準書式は実行環境のカルチャに引っ張られる。これが次のハマりどころに直結します。

ハマりポイント: 知らないと一晩飛ぶやつ

ここからが本題みたいなもんです。コピペで動かしても、この2つを踏むと「なぜか値が変」になります。

① mm と MM の取り違え(分が月になる)

正直に言うと、俺もこれで30分溶かしたことがあります。

ログの時刻がなんかおかしい。そう思って延々コードを追ってたら、書式が HH:MM になってた、というオチ。

mm が分、MM が月。HH:MM って書くと、時のあとに「月」が出ます。

var dt = new DateTime(2026, 6, 30, 14, 5, 9);

Console.WriteLine(dt.ToString("HH:mm"));   // 14:05  ← 正しい(時:分)
Console.WriteLine(dt.ToString("HH:MM"));   // 14:06  ← 月が出てる(6月→06)

実行結果(HH:MM で分のはずが月の 06 が出る・.NET 9 で再現):

mm と MM の取り違えで分が月になる実行結果の再現

エラーは出ない。14:06 ってそれっぽい値が出るから、テストでも気付きにくい。

6月だからたまたま 06。月初の 00:00 付近だと、「分」と区別すらつかなくなります。これがマジでタチ悪い。

対策はこれだけ。時刻系(HH:mm:ss)は全部小文字、日付系は yyyy/MM/dd で月だけ大文字。口で一度唱えてから書くと踏まなくなります。

② CultureInfo を指定しないと環境で表示が崩れる

これもやられました。

開発機(日本語環境)では 2026/06/30 ってちゃんと出るのに、本番サーバーに載せたら 6/30/2026 になってた、みたいなやつ。

原因は、標準書式("d" とか)や DateTime.Parse が、実行環境のカルチャを見にいくから。

var dt = new DateTime(2026, 6, 30);

// 実行環境のカルチャ次第で形が変わる
Console.WriteLine(dt.ToString("d"));
// ja-JP なら 2026/06/30、en-US なら 6/30/2026

// 環境に依存させたくないなら InvariantCulture を明示する
Console.WriteLine(dt.ToString("yyyy/MM/dd", CultureInfo.InvariantCulture));
// どの環境でも 2026/06/30

サーバーのロケール設定や、和暦が有効な環境だと、"D" で「令和8年」が出ることすらある。

判断はシンプルです。ログ・ファイル名・連携みたいに「いつ・どこで動いても同じ形であってほしい」場面は、必ず CultureInfo.InvariantCulture を渡す。逆に画面表示でユーザーの言語に合わせたい時だけ、あえてカルチャに任せる。

yyyy/MM/dd みたいにカスタム書式で桁まで固定してても、月名や曜日名(ddd)は言語で変わります。連携用途なら InvariantCulture を付けとくのが安全。

もうひとつ落とし穴があって。カスタム書式の中の /: は、実は「区切り文字」のプレースホルダ扱いなんですよね。これもカルチャで化けます。ドイツ語環境(de-DE)だと yyyy/MM/dd2026.06.30 になる。区切りまでガチで固定したいなら、yyyy'/'MM'/'dd とクオートで囲むか、InvariantCulture を渡すのが確実です。

現場メモ: 日付フォーマットで時間を溶かさないために

流通系の基幹システムの保守をやってた頃の話。夜間バッチが吐くログのタイムスタンプがバラバラで、障害調査のたびに「このログとこのログ、どっちが先??」で消耗してました。

原因は単純。書いた人ごとに yyyy/MM/dd HH:mm だったり MM/dd HH:mm:ss だったり、ミリ秒があったりなかったり。

そこからの学びは1個だけ。プロジェクトの頭で「ログは yyyy-MM-dd HH:mm:ss.fff で統一」と決めて、共通メソッドに閉じ込める

public static class DateFmt
{
    // ログ・連携はこれを通す。書式の散らばりを1箇所に集約する。
    public static string ForLog(DateTime dt)
        => dt.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
}

こうしとくと、後から「ミリ秒も足したい」となっても1箇所直すだけ。いい感じに保守が楽になります。

ちなみに今回は「日付 → 文字列」の整形の話でした。逆向きの「文字列 → DateTime」、つまりユーザー入力やCSVの日付を読む側でハマる人は、DateTime.TryParse の使い方をまとめた記事のほうが効きます。後半の関連記事に置いときました。

まとめ

要点はこれだけ。

  • 画面は yyyy/MM/dd、ファイル名は yyyyMMdd_HHmmss、ログは yyyy-MM-dd HH:mm:ss.fff、連携は ISO 8601
  • MM は月、mm は分。時刻系は全部小文字で覚える
  • 環境で形を変えたくないなら CultureInfo.InvariantCulture を明示
  • 書式は共通メソッドに閉じ込めて散らばらせない

C# の日付・時刻まわりは、標準ライブラリ系の解説書を1冊手元に置いておくと、TimeSpanDateTimeOffset まで地続きで押さえられて、結局そっちが早いです。

このページ、必要な行だけコピペして使ってください。

よくある質問

Q1. yyyyMMdd と書いたのに区切りが入ってしまうのはなぜ?

書式文字列を二重引用符で正しく囲めていないか、文字列補間の中で {dt:yyyyMMdd} の形になっていない可能性が高いです。dt.ToString("yyyyMMdd") なら 20260630 のように区切りなしで出ます。$"{dt:yyyyMMdd}" でも同じ結果になります。

Q2. HH と hh はどう違いますか?

HH が24時間表記(0〜23)、hh が12時間表記(1〜12)です。hh を使う時は tt(午前/午後)を一緒に付けないと、午後2時なのか午前2時なのか区別できなくなります。業務ログは原則 HH の24時間でそろえるのが無難です。

Q3. ミリ秒は fff と FFF のどちらを使えばいいですか?

固定で3桁出したいなら fff、末尾のゼロを省きたいなら FFF(大文字)です。ログの桁をそろえて読みやすくしたい場面では fff のほうが扱いやすいです。秒の小数を7桁まで出したい場合は fffffff まで指定できます。

Q4. 開発機と本番で日付の表示が違うのを直したいです。

標準書式("d""D")や Parse が実行環境のカルチャを見ているのが原因です。dt.ToString("yyyy/MM/dd", CultureInfo.InvariantCulture) のようにカスタム書式とカルチャを両方明示すれば、どの環境でも同じ形で出力できます。

Q5. now と書くだけで現在時刻が入りますか?

DateTime.Now がローカル時刻、DateTime.UtcNow が協定世界時です。サーバーをまたぐ連携では UtcNow で持っておき、画面表示の直前にローカルへ変換するのが事故りにくいやり方です。タイムゾーンの扱いは関連記事のほうで詳しく書いています。

次に読むべき記事

以上!

同じ罠でログの時刻を溶かしてる人いたら、どんどんシェア待ってるぜ!!


執筆者

バイブス父さん — 業務 SE 7 年 (SIer 正社員 2 / フリーランス 5)。 現職は SEO 直轄部の AI アドバイザー兼 PL、 副業で中小 SIer の CTO。 SIer の正社員からフリーランスに転じ、 複数のエージェント経由で案件を回してきた経験ベースで「業務 SE 視点」 の技術 + キャリア記事を書いています。

🐦 X: @hiro_progra0524 (日々の現場メモ更新中)
📝 About Me で経歴詳細を見る

この記事のコードと手順は ぜんぶ動作検証済み。 安心して現場で試してくれ。
バイブス父さん

現役の業務SE。C# / SQL Server 保守の現場から、コードも人もキャリアも全部書く。 実体験ベース。

運営者について