C# 初級講座
VB2015 VB2017 VB2019 Visual Studio 2022

第11回 日付の書式

2022/6/12

この記事が対象とする製品・バージョン

Visual Studio 2022 Visual Studio 2022 対象です。
Visual Studio 2019 Visual Studio 2019 対象です。
Visual Studio 2017 Visual Studio 2017 対象です。
Visual Studio 2015 Visual Studio 2015 対象です。
Visual Studio 2013 Visual Studio 2013 対象です。
Visual Studio 2012 Visual Studio 2012 対象ですが、一部当てはまりません。
Visual Studio 2010 Visual Studio 2010 対象ですが、一部当てはまりません。
Visual Studio 2008 Visual Studio 2008 対象ですが、一部当てはまりません。
Visual Studio 2005 Visual Studio 2005 対象ですが、一部当てはまりません。
Visual Studio.NET 2003 Visual Studio.NET 2003 対象ですが、一部当てはまりません。
Visual Studio.NET 2002 Visual Studio.NET (2002) 対象ですが、一部当てはまりません。
  Visual Studio Code 対象です。

 

目次

 

1.書式

日付を文字列で表現する方法はたくさんあります、「2020年3月10日 5時18分21秒」 と書いてもよいし、「2020/3/10 5:18:21」、「3/10/2020 5:18:21 AM」、「10/03/2020 05:18:21」 など様々な表現方法があります。

こういった表現の形式の違いを「書式」(しょしき)と呼びます。上記の例では同じ日付で書式が違うということです。

 

単純に ToString メソッドなどを使って日付を文字列化した場合、実行環境の設定に応じた書式を使って文字列化されます。Windowsの場合は、コントロールパネルの設定です。

DateTime date = new DateTime(2020, 3, 10, 5, 18, 21);
Console.WriteLine(date.ToString());

このプログラムを実行すると一般的なWindowsの日本語環境では「2020/03/10 5:18:21 」と表示されます。コントロールパネルなど環境の設定によって異なる表示になるので、常にそうなるという保証はありません。

 

2.プログラムでの書式の指定

2-1.プログラムでの書式の指定

プログラムで書式を明示的に指定することもできます。書式を指定しない場合、実行する環境によって異なる表示や出力になりますから、どのような環境でも同じ表示・出力にしたい場合は、書式を指定するのが普通です。

書式には.NETであらかじめ定義された書式を表す 標準の書式 と プログラマーが自由に形式を指定できる カスタムな書式 の2種類があります。多くのプログラマーはカスタムな書式を使って自由に書式を指定する傾向にあります。(私は標準の書式を使っているプログラムを滅多に見ません。)

標準の書式 あらかじめ.NETに組み込まれている書式の中から選択して指定します。
カスタムな書式 書式を自由に組み立てて指定します。

 

書式の指定にはちょっと独特なルールが適用されます。

次の例ではカスタムな書式を使って日付を「2020年3月10日 5時18分21秒」の形式で表示します。

2行目はToStringメソッドで書式を指定する例です。ToStringでは引数に文字列として書式を指定します。、3行目は $" "  の補完文字列で書式を指定する例です。補完文字列では埋め込んだ変数や式の後を : で区切って書式を指定します。

DateTime date = new DateTime(2020, 3, 10, 5, 18, 21);
Console.WriteLine(date.ToString("yyyy年M月d日 H時m分s秒"));
Console.WriteLine($"{date:yyyy年M月d日 H時m分s秒}");

この例を実行すると次のように表示されます。

2020年3月10日 5時18分21秒
2020年3月10日 5時18分21秒

 

2-2.書式のルール

このプログラムで「yyyy年M月d日 H時m分s秒」となっている文字列が書式を表す文字列です。   この部分は ToString の場合でも、補完文字列の場合でも同じです。その他の機能で書式を指定できるものもありますが、この指定の仕方は変わりません。

 

書式の中で yyyy は年に置き換わり、Mは月に置き換わるというようにルールに従った置き換えが行われ結果として文字列が生成されます。

このような yyyy や M などを「書式指定子」(しょしきしていし)と呼びます。

次の図では書式指定子を黄色で示しています。書式指定子はそれが意味する値に置き換えられます。それ以外の文字はそのまま出力されます。

書式指定子の位置は自由で、好きなところに記述できます。「今はM月!yyyy年だね。」のような書式指定も有効です。このように自由に指定できるのがカスタム書式です。

 

よく使う書式指定子には次のものがあります。

yyyy 年を4桁 例 2020 HH 24時間制の時間を2桁 例 15
yy 年を2桁 例 20 H 24時間制の時間を1桁または2桁 例 15
MM 月を2桁 例 03 hh 12時間制の時間を2桁 例 03
M 月を1桁または2桁 例 3 h 12時間制の時間を1桁または2桁 例 3
MMMM 月の名前 例 March mm 分を2桁 例 05
MMM 月の短縮形 例 Mar m 分を1桁 例 5
dd 日を2桁 例 10 ss 秒を2桁 例 46
d 日を1桁または2桁 例 10 s 秒を1桁 例 46
dddd 曜日 例 土曜日 : 時刻の区切り記号 例 :
ddd 曜日の短縮形 例 土 / 日付の区切り記号 例 /

書式指定子は大文字と小文字を区別する点に周囲してください。Mは月で、mは分です。Hとhも違います。

この表の他にもミリ秒を表す fff やAM/PMなどを表す tt などもあります。日時で使用できるカスタム書式指定子の一覧は下記で確認できます。

カスタム日時形式文字列 | Microsoft Docs

 

置き換えられる値は実行環境の地域や言語(カルチャー)によって異なります。特徴的なのは曜日をに置き換えられる dddd と ddd で、実行するカルチャーによって英語や中国語などさまざまな言語に置き換えられます。Windowsの場合、既定ではコントロールパネルの設定に基づいてどの地域・言語で実行されているか自動的に判断されます。

 

2-3.書式指定子のエスケープ

書式指定子の前に \ を入力するとその直後の書式指定子は効果を失い通常の文字扱いになるという特別ルールがあります。この連なり(シーケンス)をエスケープシーケンスと呼びます。

ただ、 C# では \t はタブ、\n は改行、のように C# としてのエスケープシーケンスも定義されており、こちらのエスケープシーケンスの方が先に処理されます。そのため単純に \y などと記述すると未定義のエスケープシーケンスとしてエラーになります。

そこで、書式指定子でエスケープシーケンスを使いたい場合は、逐語的文字列 @" " を使って、\ を付けるのが簡単です。逐語的文字列内では C# のエスケープシーケンスは機能しないルールだからです。

DateTime date = new DateTime(2020, 3, 10, 5, 18, 21);
Console.WriteLine(date.ToString(@"\y\y\y\y は yyyy になります。"));
Console.WriteLine($@"{date:\y\y\y\y は yyyy になります。}"); 

この例を実行すると次のように表示されます。

yyyy は 2020 になります。
yyyy は 2020 になります。

 

 

2-4.区切り記号

ちょっと注意が必要なのは : や / も書式指定子であるということです。つまり、書式の中でこれらの記号を使用すると何か別のものに置き換えられる可能性があります。

そのため、区切り文字を固定化したい場合は、エスケープシーケンスを使います。

次の例では / と : はエスケープされているので、常に / や : として出力されます。

DateTime date = new DateTime(2020, 3, 10, 5, 18, 21);
Console.WriteLine(date.ToString(@"yyyy\/M\/d H\:m\:s")); 

 

多くのプログラマーはこのことを知らずにエスケープしないで : や / を含む書式を使っています。

たとえば、次のプログラムには問題があるかもしれません。

DateTime date = new DateTime(2020, 3, 10, 5, 18, 21);

Console.WriteLine(date.ToString("yyyy/M/d H:m:s"));

これを実行するとおそらく次のように出力されると思います。


2020/3/10 5:18:21

/ や : は何にも置き換えられておらず「時」や「分」の場合と同じようにそのまま出力されています。

ですが、これは、実行環境は日本やアメリカに設定されている場合の話です。世界の国や言語には日付の区切りが - や . だったり、時刻の区切りが . だったりするものがあり、これらの環境でこのプログラムを実行すると書式指定子としての / や : はその記号に置き換えられます。

たとえば、同じプログラムをトルコ語の文化で実行すると次のように日付の区切りが . (ドット)になって出力されます。


2020.3.10 5:18:21

 

 

 

3.和暦

「令和3年3月10日」と「2020年3月10日」は同じ日なので、この表現の違いも書式です。

ただ、平成とか令和のような日本の年号は非常に特殊で、DateTimeのリファレンスでも上の方で和暦の取扱いについての注意書きがわざわざ書いてあります。

和暦で表示するプログラムは次のようになります。

DateTime date = new DateTime(2020, 3, 10, 5, 18, 21);

var japan = new System.Globalization.CultureInfo("ja-JP");
japan.DateTimeFormat.Calendar = new System.Globalization.JapaneseCalendar();
Console.WriteLine(date.ToString(@"ggy年M月d日 H時m分s秒", japan)); 

実行すると次のように表示されます。


令和2年3月10日 5時18分21秒

 

.NETには、世界の国と地域や言語に対応した機能を実現するために「カルチャー」という仕組みがあります。和暦のように日本の文化に基づいた機能はカルチャーを使用して実現します。

カルチャーは CultureInfoクラス(読み方:CultureInfo=カルチャーインフォ)で表現します。この例では変数 japan に CultureInfoクラスのインスタンスを設定します。CultureInfoクラスのコンストラクターでは言語と地域を組み合わせた文字列を使って、どの「カルチャー」であるかを指定します。jaは日本語、JPは日本を表しており、"ja-JP" というもじれつが 日本文化を表現するカルチャーです。

日本では、西暦の日付もよく使いますから、日本文化では、西暦を使うか和暦を使うか設定変更できるようになっています。フレームワークには暦を表現する xxxCalendar クラスがいくつか用意されており、和暦は JapaneseCalendarクラス(読み方:JapaneseCalendar=ジャパニーズカレンダー)です。このクラスのインスタンスをカルチャーに設定します。

そのうえで、ToStringメソッドの第2引数にこのカルチャーを設定すると、ここでは日本文化の書式を使えることになります。日本文化では元号は gg で表します。 y は元号に基づいた年になります。

ということで、このプログラムを実行すると「令和2年」と表示されるわけです。ちなみに、2019年5月~12月だと「令和元年」と出力されます。「1年」ではなく「元年」というところもちゃんと日本文化に沿っているわけです。

 

4.練習問題

問1.日本語環境で実行した場合、value の値は何になりますか?
DateTime date = new DateTime(2028, 12, 9, 15, 3, 21);
string value = date.ToString("yyyy");
2028
10
yyyy
問2.value の値は何になりますか?
DateTime date = new DateTime(2028, 12, 9, 15, 3, 21);
string value = date.ToString("h時");
15時
3時
03時
問3.日本語環境で実行した場合、value の値は何になりますか?
DateTime date = new DateTime(2028, 12, 9, 15, 3, 21);
string value = date.ToString(@"yyyy\/m\/d");
2028/12/9
2028\/12\/9
2028/3/9
2028\/3\/9

 

 

5.カルチャー

5-1.カルチャーの使用

日本以外にもさまざまな言語と地域でそれぞれの風習があります。和暦と同様にカルチャーを使うとその言語と地域に合わせた機能が使用できます。

日本とトルコのカルチャーを明示的に指定して実験してみましょう。カルチャーはToStringの第2引数で指定できます。

下記のプログラムではまったく同じ書式を指定して日付を出力します。カルチャーは異なります。

DateTime date = new DateTime(2020, 3, 10, 5, 18, 21);

//日本のカルチャーで実行
var japan = new System.Globalization.CultureInfo("ja-JP");
Console.WriteLine(date.ToString("yyyy/M/d H:m:s", japan)); //2020/3/10 5:18:21

//トルコのカルチャーで実行
var turkey = new System.Globalization.CultureInfo("tr-TR");
Console.WriteLine(date.ToString("yyyy/M/d H:m:s", turkey)); //2020.3.10 5:18:21

カルチャーはプログラム上では CultureInfoクラス(読み方:CultureInfo=カルチャーインフォ)で表現されます。名前空間はSystem.Globalization(読み方:Globalization=グローバリゼーション)です。この名前空間には国際対応の機能が集まっています。CultureInfoクラスのコンストラクターの引数で、対象のカルチャーを指定します。カルチャーは地理的な場所と言語の組み合わせで異なるので、この2つを言語コードと国コードを組み合わせた文字列で指定します。日本は ja-JP 、トルコは tr-TR です。なお、規格上、ja(日本語) は日本(JP)固有ですが、トルコ語(tr)はキプロス(CY)でも使用する文化があるので、tr-CY (キプロスのトルコ語文化)というカルチャーも存在します。

これを実行すると次の通り表示されます。

2020/3/10 5:18:21
2020.3.10 5:18:21

カルチャーと書式の両方を指定しているので、世界中どのような環境で実行しても必ずこの通り出力されます。

結果を比べると一目瞭然で、日本では日付が / で区切られているのに、トルコでは . で区切られています。

この例では明示的にカルチャーを指定していますが、カルチャーを指定しなかった場合、自動的にWindowsなど環境に応じたカルチャーが採用されるので、同じ書式を使ったプログラムでも実行環境によっては違う結果になるということが理解いただけると思います。

 

5-2.デフォルトのカルチャーの変更

一応、プログラムで明示的にデフォルトのカルチャーを指定することもできるので、どうしてもカルチャーを固定したい場合は、必要な場所で逐一カルチャーを指定するのではなく、プログラム開始時点でデフォルトのカルチャーを指定しておくのが楽です。

次のプログラムはデフォルトのカルチャーを日本に設定します。これ以降、このプログラムでカルチャーが明示されていない場所ではすべて日本のカルチャーが使用されます。


System.Globalization.CultureInfo.CurrentCulture = new System.Globalization.CultureInfo("ja-JP");

 

次の回では、期間を扱います。

C#初級講座講座 次の回へ