より良いエンジニアを目指して

1日1つ。良くなる!上手くなる!

TimeSpanのToStringで書式指定したら例外! エスケープ必須です

職場でTimeSpan型の値をToStringしてハマった話をします。

DateTime型をフォーマット指定して出力する場合は、以下のような形。

var text = dateTime.ToString("yyyy/MM/dd HH:mm:ss");

f:id:rimever:20190306205528p:plain
.NET FiddleだとDateTime.Now()がサーバー時刻になりますね。ま、そりゃそうか。

よく、Yは大文字なのかとか悩んでGoogleに相談してますが。(実は時間はHでもhでも可能です)

ですが、TimeSpanの場合は、

var text = timeSpan.ToString("hh:mm:ss");

とすると

f:id:rimever:20190306210048p:plain
System.FormatException: Input string was not in a correct format.

になります。

カスタム時間間隔書式指定文字列 | Microsoft Docs

上記のMSDNを読めばわかりますが、hhなどの書式以外の文字列を指定する場合はエスケープが必須となります。たとえスペースでもです。

var text = timeSpan.ToString("hh\:mm\:ss");

としなければなりません。

var text = timeSpan.ToString(@"d\日h\時\間m\分s\秒");

一文字ずつエスケープです。なぜこうなったのでしょうか。

といっても書式以外の文字列に対して''で囲んでもOKのようです。

var text = timeSpan.ToString(@"d'日'h'時間'm'分's'秒'");

'で囲む分、エスケープの1文字に対して2文字使ってしまうので、長い文字列には'、一文字ならエスケープという使い分けを求めているようです。

いや、求めないで欲しいです。

これを読んでいるアナタは笑っていいのですが、私もMSDNを見ました。サンプルソースだけを見て

なんか、余計な文字(エスケープ文字)が入ってるけど、俺のソースにはいらねーや

エスケープせずにコードを動かして何度も例外になってたんですから。

なぜだ!と共有したく検索したら、StackOverflowで同様の質問をしている方がいました。

stackoverflow.com

私の英語力で解釈したところ、「DateTimeのフォーマットは国ごとに違うけど、TimeSpanのフォーマットは国ごとには違わない。DateTimeとTimeSpanのフォーマットが違うのは合理的」といったような回答です。

が、どうなのかな。

だからといって片方はエスケープ、もう片方はエスケープしないフォーマットにする理由があったのかな、と。

とはいえ、別々に設計したからこうなった、というのはそうなんでしょうね。

で、後になって気づいたら、「あ、違っちゃったー」みたいなことなんでしょうかね。

うちの職場なんて同じようなものが全く違った設計で作られていることが、あるあるですし。