LoginSignup
4
3

More than 5 years have passed since last update.

DateTime.ToString() による月や曜日の英語表現にはロケールの指定が必須

Last updated at Posted at 2016-08-17

Qiita を利用されている方、および開発物のユーザーの多くは日本語圏の方であろうと思います。

DateTime.Now.ToString("MMM") => "8" ??

"MMM" カスタム書式指定子は、月の省略名を表します。

と MSDN の記事「カスタム日時書式指定文字列」に書かれていますが、

Console.WriteLine(DateTime.Now.ToString("MMM"));

のように記述すると、5月であれば "May" ではなく、"5" のように数字できっと表示されてしまうでしょう。syslog など、英語表現の月略名を使用したいときに困ります。

原因と解決法

おそらく日本語版の WindowsOS で動かしていますよね?これは、OS のロケール設定(コントロールパネル「システム」で設定する「日付の形式」など)によって「月の完全名」「月の省略名」「曜日の完全名」「曜日の省略名」の表現が異なるためです。ちなみに日本語ロケール (ja-JP) で「月の完全名」は 5月であれば "5月"となります。

解決法1:DateTime.ToString()メソッド呼び出し時にインバリアント、または英語圏のロケールを指定する

var result = DateTime.Now.ToString("MMM", System.Globalization.CultureInfo.InvariantCulture);

または

var result = DateTime.Now.ToString("MMM", System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));

のように、DateTime.ToString メソッドにおいてカルチャに依存しない (インバリアントな) 、または英語圏のロケールを指定します。

解決法2:DateTimeFormatInfo.AbbreviatedMonthNamesプロパティを使用する。

DateTimeFormatInfo クラスのコンストラクタの処理は、

カルチャに依存しない (インバリアントな) DateTimeFormatInfo クラスの新しい書き込み可能インスタンスを初期化します。

だそうです。そこで

var result = (new System.Globalization.DateTimeFormatInfo()).AbbreviatedMonthNames[DateTime.Now.Month - 1];

とオブジェクトを生成してから DateTimeFormatInfo.AbbreviatedMonthNames プロパティを利用することで、英語表記での月の省略名を得られます。

おなじく

var result = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.AbbreviatedMonthNames[DateTime.Now.Month 
- 1];

var result = System.Globalization.DateTimeFormatInfo.InvariantInfo.AbbreviatedMonthNames[DateTime.Now.Month - 1];

でも可能です。

解決法3:スレッドのカルチャにインバリアント、または英語圏のロケールを指定する。

System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;

// ...同一スレッドであれば何か処理をはさんでも可

var result = DateTime.Now.ToString("MMM");
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");

// ...同一スレッドであれば何か処理をはさんでも可

var result = DateTime.Now.ToString("MMM");

と、スレッドのカルチャをインバリアント、または英語圏のロケールに設定することで、英語表記で得られるようになります。アプリケーション自体がコンピューターチック(インバリアントなカルチャ)なものであれば、この方法でアプリケーション初期化時にスレッドのカルチャをインバリアントに設定してしまうほうがいろいろ捗ると思います。

解決法4:自前で表現を用意する。

var result = (new string[] { "Jan", "Feb", "Mar", ...(略)... , "Dec"})[DateTime.Now.Month - 1];

としても、望む結果をもちろん得られます。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3