C# 初級講座 |
![]() ![]() ![]() ![]() |
2022/6/6
この記事が対象とする製品・バージョン
![]() |
Visual Studio 2022 | ◎ | 対象です。 |
![]() |
Visual Studio 2019 | ◎ | 対象です。 |
![]() |
Visual Studio 2017 | ◎ | 対象です。 |
![]() |
Visual Studio 2015 | ◎ | 対象です。 |
![]() |
Visual Studio 2013 | ◎ | 対象です。 |
![]() |
Visual Studio 2012 | ◎ | 対象です。 |
![]() |
Visual Studio 2010 | ◎ | 対象です。 |
![]() |
Visual Studio 2008 | ◎ | 対象です。 |
![]() |
Visual Studio 2005 | ◎ | 対象です。 |
![]() |
Visual Studio.NET 2003 | ◎ | 対象です。 |
![]() |
Visual Studio.NET (2002) | ◎ | 対象です。 |
Visual Studio Code | ○ | 対象です。 |
目次
今回は C# での日付と時刻の扱いについて説明します。少し教科書的な退屈な説明になってしまいますが、日付と時刻の扱いをちゃんと知らないプログラマーは意外と多く、ちょっと日付を扱うプログラムを書くだけで苦労しているプログラマーもいます。たとえば、今月の月末は何曜日でしょうか?基本的なことがわかっていれば1行で答えを書けます。基本事項を押さえておきましょう。
今回はまとまったプログラムを作りませんが、小さなサンプルが複数登場します。
サンプルを実際に試す場合は、Windows フォーム アプリにボタンを配置してClickイベントにプログラムするなどしてみてください。
ただ読んでいるよりは実際にサンプルを入力して実行してみたほうが得られるものは多いので、特に急いでいなければやってみることをおすすめします。
一番基本的なことは C# では日付と時刻は DateTime 型 (読み方:DateTime=デイトタイム)で表現するということです。これを日付型とも呼ぶ場合もあります。DateTime型の実体はDateTime構造体です。勉強不足のプログラマーは日付と時刻を文字列型(string)で表現してしまいます。
DateTime構造体は 西暦1年1月1日 0時0分0秒 から 西暦 9999年12月31日の終わりまで範囲の日時を100ナノ秒単位で表現することができます。
なお、プログラムの世界では「日付」という言葉には「時刻」む場合と含まない場合の両方があります。ひとまずは単に「日付」と書いてある場合、「時刻」も含んでいるという前提で理解しておくのが良いと思います。この後の説明でも特に注意しない限りこの意味で「日付」という言葉を使用します。
システム日付はそのプログラムを実行した時点での日付と時刻を意味しています。つまり「今」という意味です。DateTimeの静的プロパティ Now (読み方:Now=ナウ)で簡単に取得できます。
DateTime myDate = DateTime.Now;
MessageBox.Show(myDate.ToString());
後で説明しますが、AddDaysメソッド(読み方:AddDays=アドデイズ)などを使って、何日後・何日前という日付を簡単に計算できます。
たとえば、昨日の日付は次のように取得できます。
DateTime myDate = DateTime.Now.AddDays(-1);
MessageBox.Show(myDate.ToString());
明後日は次の通りです。
DateTime myDate = DateTime.Now.AddDays(2);
MessageBox.Show(myDate.ToString());
日常会話で、単に「昨日」や「明後日」というと時刻は含みませんが、プログラムでは時刻も保持しています。上記のプログラムを実行すると時刻も表示されるのでわかると思います。気になる場合は、Dateプロパティを使うことで、時刻部分を 0時0分0秒にできます。
DateTime myDate = DateTime.Now.Date.AddDays(2);
MessageBox.Show(myDate.ToString());
これらの使い方はこの記事の少し後でもう少し説明します。
プログラムの中で年月日や年月日時分秒を指定して特定の値の日付を生成するには DateTime構造体のコンストラクターを使用します。DateTime構造体として日付を保持しておくことで、AddDaysなど便利なメソッドやプロパティを使用できるようになります。それらについてはこの記事のもう少し後で説明します。
次の例では028年8月20日を表すDateTime構造体を生成しています。
DateTime myDate = new DateTime(2028, 8, 20);
MessageBox.Show(myDate.ToString());
DateTime構造体は構造体なので 宣言しただけでインスタンスを作成できますが、ここでは年月日を指定するコンストラクターの機能を呼び出すためにあえてnewを使ってコンストラクターを呼び出しています。
時分秒も含めて指定できるコンストラクターのオーバーロードもあります。
次の例ではmyDate は 2028年8月20日 15時5分40秒になります。
DateTime myDate = new DateTime(2028, 8, 20, 15, 5, 40);
MessageBox.Show(myDate.ToString());
もう1つ引数を増やしてミリ秒を指定することもできます。
文字列を解釈してDateTimeの値を生成することもできます。
もっとも簡単なのは Parseメソッド(読み方:Parse=パース) です。
このメソッドは自動的にいろいろ解釈してくれるので何も考えずに次のように使用できます。
DateTime myDate = DateTime.Parse("2028/8/20");
MessageBox.Show(myDate.ToString());
Parseメソッドは結構柔軟にいろいろ解釈してくれます。こんな風に書いても大丈夫です。
DateTime myDate = DateTime.Parse("8.20.2028");
MessageBox.Show(myDate.ToString());
ただ、Parseメソッドは自動的に解釈してくれるので便利な半面、予想外の結果やエラーになる可能性もあり、良く知らないで使用するのはおすすめではありません。
Parseメソッドの解釈に影響を与えるのは.NETで「カルチャー」と呼ばれるもので、簡単に言うと(少し不正確ですが)実行している環境が日本語環境なの、フランス語環境なのか、スワヒリ語環境なのかというような違いです。Windowsで実行している場合は、Windowsで設定している内容が既定のカルチャーとして使用されます。
たとえば、実行する環境の設定が日本になっていれば、平成や令和なども解釈できます。
次のプログラムを実行すると、たとえば「2018/01/15 0:00:00」と表示されます。
DateTime myDate = DateTime.Parse("平成30年1月15日");
MessageBox.Show(myDate.ToString());
次のプログラムでは R は令和と解釈され、たとえば「2030/09/03 0:00:00」と表示されます。
DateTime myDate = DateTime.Parse("R12/9/3");
MessageBox.Show(myDate.ToString());
実行する環境が日本以外の別の文化(カルチャー)担っている場合は、日本でしか通じない日付はエラーになり、代わりに現地で通用する日付が解釈できるようになります。たとえば、フランス語環境では、次のプログラムは2018年1月15日と解釈されます。日本の環境ではではエラーになります。
DateTime myDate = DateTime.Parse("15 janvier 2018");
MessageBox.Show(myDate.ToString());
というわけなので、Parseを単純に利用する場合は、自分のパソコンでしか実行しないなど実行環境のカルチャーが保証される場合だけにしましょう。または、カルチャーを第2引数に指定してParseを使用する方法もあります。カルチャーについては別の機会に説明します。カルチャーは日付以外にも小数点の表現などに影響します。
DateTime型は日付に対してさまざまな便利な機能を提供してくれます。これらの機能の多くはDateTime型のメンバー(メソッドとプロパティ)を呼び出して使用できます。よく使うプロパティは次の通りです。
説明欄にプログラムのサンプルも載せたのでこれを見るだけでだいたいわかると思います。
プロパティ | 読み方 | 説明 |
---|---|---|
|
デイト | 時刻を抜いた日付を取得します。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 DateTime date = d.Date; // 2028年8月29日 0時0分0秒 を表します。 |
|
デイ | 日付を取得します。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 int day = d.Day; // 29 |
|
デイオブウィーク | 曜日を返します。→ 参考
C# サンプル 曜日を取得する DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 DayOfWeek youbi = d.DayOfWeek; // Tuesday |
|
アワー | 時間を取得します。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 int hour = d.Hour; // 3 |
|
ミニットゥ | 分を取得します。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 int minute = d.Minute; // 40 |
|
マンス | 月を取得します。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 int month = d.Month; // 8 |
|
セカンド | 秒を取得します。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 int second = d.Second; // 51 |
|
タイムオブデイ | 時刻部分だけを取得する意図で、午前0時0分0秒からの経過時間を取得します。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 TimeSpan time = d.TimeOfDay; // 3時間40分51秒 を表します。※3時40分51秒ではない。 |
|
イヤー | 年を取得します。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 int year = d.Year; // 2028 |
明日の日付やおとといの日付、来年や50日後などはメソッドを使って取得することができます。
よく使うメソッドは次の通りです。
メソッド | 読み方 | 説明 |
---|---|---|
|
アドデイズ | 指定した日数を加えた日付を取得します。マイナスを指定して過去にさかのぼることもできます。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 DateTime date = d.AddDays(5); // 2028年9月3日 3時40分51秒 を表します。 |
|
アドアワーズ | 指定した時間を加えた日付を取得します。マイナスを指定して過去にさかのぼることもできます。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 DateTime date = d.AddHours(30); // 2028年8月30日 9時40分51秒 を表します。 |
|
アドミニッツ | 指定した分を加えた日付を取得します。マイナスを指定して過去にさかのぼることもできます。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 DateTime date = d.AddMinutes(30); // 2028年8月29日 4時10分51秒 を表します。 |
|
アドマンスズ | 指定した月数を加えた日付を取得します。マイナスを指定して過去にさかのぼることもできます。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 DateTime date = d.AddMonths(-10); // 2027年10月29日 3時40分51秒 を表します。 |
|
アドイヤーズ | 指定した年数を加えた日付を取得します。マイナスを指定して過去にさかのぼることもできます。 DateTime d = new DateTime(2028, 8, 29, 3, 40, 51); // 2028年8月29日 3時40分51秒 DateTime date = d.AddYears(1); // 2029年8月29日 3時40分51秒 を表します。 |
日数や時間をたして、月末や24時を超えたときにちゃんと次の日や月になってくるのがポイントです。8月31日に AddDays で 1日 を追加すると9月1日になってくれます。当たり前ですが、8月32日のようなありえない日付にはなりません。
DateTime date = new DateTime(2028, 8, 31).AddDays(1);
MessageBox.Show(date.ToString()); // 2028年9月1日を表します。
ひき算の方も同じです。たとえば、2028年1月15日に AddMonthsで -1 を指定して 1か月ひき算すると、2027年12月15日になります。
DateTime date = new DateTime(2028, 1, 15).AddMonths(-1);
MessageBox.Show(date.ToString()); // 2027年12月15日を表します。
3月31日に1か月追加すると、4月には31日がないので30日になります。
DateTime date = new DateTime(2028, 3, 31).AddMonths(1);
MessageBox.Show(date.ToString()); // 2028年4月30日を表します。
このあたりの計算は期待通りに動作してくれるので、頭を悩ませることはないと思います。
DateTime型の操作の一例としてよくある月末の日付の求め方を紹介します。
まずは、年月がわかっている場合です。たとえば、2028年2月の月末は次のように求められます。
1か月追加して翌月の月初にしてから1日引くと月末がわかるという寸法です。
//月の始めの1日の日付を作成して、1か月後の1日前を求める。
DateTime lastDate = new DateTime(2028, 2, 1).AddMonths(1).AddDays(-1);
MessageBox.Show(lastDate.ToString()); // 2028年2月29日を表します。
システム日付など任意の年月日があるときに月末を求めるには、上記のやり方をまねて次のようにします。
//月の始めの1日の日付を作成して、1か月後の1日前を求める。
DateTime targetDate = DateTime.Now;
DateTime lastDate = new DateTime(targetDate.Year, targetDate.Month, 1).AddMonths(1).AddDays(-1);
MessageBox.Show(lastDate.ToString()); // 月末の日付を表します。
同じ発想で次のようのプログラムすることもできます。この例では日付分の日数をマイナスして1日プラスすることで1日の日付を作りだします。この方法だと時刻部分が保持されるので、気になるならDateプロパティを使って時刻部分が0:00:00のインスタンスを取得します。
DateTime targetDate = DateTime.Now;
DateTime lastDate = targetDate.AddDays(-targetDate.Day + 1).AddMonths(1).AddDays(-1).Date;
MessageBox.Show(lastDate.ToString());
ところで、DateTime型の静的プロパティ DaysInMonth は年月を指定するとその月が何日まであるかを返す機能があります。これを使って月末の日付を作ることもできます。このメソッドの戻り値はDateTime型ではなく、31とか28などの単一の数値(int)です。
int lastDay = DateTime.DaysInMonth(2028, 2); // 29 を取得します。
DateTime lastDate = new DateTime(2028, 2, lastDay);
MessageBox.Show(lastDate.ToString()); // 2028年2月29日を表します。
int jikan = DateTime.Now.■;
// A
DateTime date1 = new DateTime(2025, 11, 10);
// B
DateTime date2 = DateTime.Parse("2025/11/10");
var x = new DateTime(2026, 1, 1).AddMinutes(-1).Year;
次の回では、日付の書式を扱います。