はじめに 「ファイル名用日時」は“あとから探しやすく、壊れにくい名前のコア”
バックアップファイル、エクスポートCSV、ログのローテーションファイル。
こういう「時刻付きファイル名」を付けるとき、
なんとなく DateTime.Now.ToString() をくっつけると、だいたい痛い目を見ます。
理由はシンプルで、
ファイル名には「使えない文字」があり、
ロケールによって / や : が入ったり、
ソートしたときに時系列順にならなかったりするからです。
だからこそ、「ファイル名用日時」は
ルールを決めてユーティリティ化しておく価値が高いテーマです。
基本方針:ファイル名に安全で、ソートすると時系列になる形にする
使ってはいけない文字を避ける
Windows などのファイルシステムでは、/ \ : * ? " < > | などはファイル名に使えません。DateTime.ToString() のデフォルトは、平気で / や : を含みます。
なので、ファイル名用の日時は
「数字と一部の記号だけ」で構成するのが安全です。
よく使われるのは、こんな形です。
yyyyMMdd_HHmmssyyyyMMdd_HHmmssfff(ミリ秒付き)
例:20260218_204530、20260218_204530123
この形なら、
ファイル名として安全で、
文字列としてソートしたときにそのまま時系列順になります。
実装:ファイル名用日時文字列を返すユーティリティ
秒単位のファイル名用日時
まずは秒単位のシンプルなユーティリティです。
using System;
using System.Globalization;
public static class FileNameTimeUtil
{
public static string GetFileNameTimestamp()
{
DateTime now = DateTime.Now;
return now.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture);
}
}
C#使い方の例です。
string ts = FileNameTimeUtil.GetFileNameTimestamp();
string fileName = $"backup_{ts}.zip";
Console.WriteLine(fileName);
// 例: backup_20260218_204530.zip
C#ここでの重要ポイントは、
- フォーマットを
"yyyyMMdd_HHmmss"に固定していること CultureInfo.InvariantCultureを指定して、環境によって変わらないようにしていること
です。
ミリ秒付き(衝突を減らしたい場合)
同じ秒の間に複数ファイルを作る可能性があるなら、
ミリ秒まで含めてしまうのが手軽です。
public static string GetFileNameTimestampWithMillis()
{
DateTime now = DateTime.Now;
return now.ToString("yyyyMMdd_HHmmssfff", CultureInfo.InvariantCulture);
}
C#例:backup_20260218_204530123.log
UTC を使うかローカルを使うか
「どの時間軸で管理したいか」を決める
ログ用日時と同じく、
ファイル名用日時も「UTC で統一するか」「ローカル時間でいいか」を決める必要があります。
複数サーバー間でファイルを集約する、
タイムゾーンが混在する、
といったシステムなら、UTC にそろえたほうが後々楽です。
public static string GetFileNameTimestampUtc()
{
DateTime utcNow = DateTime.UtcNow;
return utcNow.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture);
}
C#ただし、運用担当者が「日本時間で見たい」など、
ローカル時間のほうが直感的なケースもあります。
その場合は、
- ファイル名はローカル時間
- メタデータやログには UTC も別途持つ
のように、用途ごとに使い分ける設計もアリです。
実務でよくあるパターン別の例
バックアップファイル
日次バックアップなどでは、
「日付+時刻+連番」のような形がよく使われます。
string ts = FileNameTimeUtil.GetFileNameTimestamp();
string fileName = $"db_backup_{ts}.bak";
// db_backup_20260218_020000.bak
C#日次で1ファイルなら日付だけでもよいですが、
手動実行やリトライなどを考えると、時刻まで入れておくほうが安全です。
ローテーションログ
ログファイルをローテーションするときも、
ファイル名に日時を埋め込むのが定番です。
string ts = FileNameTimeUtil.GetFileNameTimestampWithMillis();
string fileName = $"app_{ts}.log";
// app_20260218_204530123.log
C#ミリ秒まで入れておけば、
同じ秒にローテーションが走っても衝突しにくくなります。
実務での注意点:フォーマットを“1箇所に固定する”
あちこちで ToString("yyyyMMdd_HHmmss") と書かない
プロジェクトのあちこちで、
それぞれが勝手に
DateTime.Now.ToString("yyyyMMdd_HHmmss")
C#と書き始めると、
そのうち誰かが "yyyy-MM-dd_HH-mm-ss" とか "yyyyMMddHHmmss" とか
微妙に違うフォーマットを使い始めます。
結果として、
- ファイル名のパターンが揃わない
- 後処理(バッチ・集計)が書きづらい
- 正規表現やパースが複雑になる
という“じわじわ効く痛み”が出てきます。
だからこそ、
public static class FileNameTimeUtil
{
public static string Now() => ...;
public static string NowWithMillis() => ...;
}
C#のように、「ファイル名用日時は必ずここを通す」という
ユーティリティを1箇所に決めておくのが大事です。
まとめ 「ファイル名用日時ユーティリティ」は“安全で探しやすい名前の型”
ファイル名用日時は、
単なる飾りではなく、
- ファイル名として安全であること
- ソートしたときに時系列になること
- 環境によって変わらないこと
といった性質を満たす“設計された文字列”です。
押さえておきたいポイントはこうです。
- フォーマットは
"yyyyMMdd_HHmmss"(+fff)のように、数字と安全な記号だけにする CultureInfo.InvariantCultureを使って、ロケール依存をなくす- UTC を使うかローカルを使うかは要件次第だが、どちらかに統一する
- バックアップ・ログ・エクスポートなど、用途ごとに同じルールを使い回す
- プロジェクト全体で「ファイル名用日時はこのユーティリティを使う」と決めて、一貫性を守る
ここまで決めてしまえば、
「とりあえず今の時刻をくっつける」から卒業して、
“壊れにくくて後から探しやすいファイル名”を、毎回迷わず付けられるようになります。
