指定した日の曜日を取得するには?[C#/VB]:.NET TIPS
DateTime/DateTimeOffset構造体やStringクラスを使用して、指定した日が何曜日かを知る方法を解説。また、六曜の取得方法についても取り上げる。
日付から曜日を表す文字列を取得するにはどうしたらよいだろうか? 本稿では、「日曜日」や「月」や「Tue」といったさまざまな形式で曜日を取得する方法を解説する。また、旧暦の六曜(「大安」や「仏滅」など)を求める方法も紹介する。
特定の方法をすぐに知りたいという方は以下のリンクを活用してほしい。
なお、曜日を取得するための機能は.NET Frameworkの当初からあるものだが、サンプルコードでは新しい機能も使っている。本稿に掲載したサンプルコードをそのまま試すにはVisual Studio 2015以降が必要である。
既定の言語で取得する:「日曜日」/「日」
日付を文字列にフォーマットするときの書式指定に「dddd」(完全な表記)か「ddd」(短縮した表記)を与えればよい。
System名前空間のDateTime構造体(あるいはDateTimeOffset構造体)のToStringメソッド、または、Stringクラス(System名前空間)のFormatメソッドに与える書式指定文字列として、「dddd」を与えると曜日の完全な表記が、また、「ddd」を与えると省略した表記が得られる(次のコード)。
ただし、この方法は実行環境の言語設定(カルチャー)に影響される。この例では日本語で出力されているが、実行しているWindowsが日本語環境だったからだ。言語を指定して曜日を得る方法は、次項で説明する。
// 例:2017年10月5日 木曜日
var theDay = new DateTime(2017, 10, 5);
// DateTime構造体のToStringメソッドを使う
string 長い曜日 = theDay.ToString("dddd");
string 短い曜日 = theDay.ToString("ddd");
Console.WriteLine($"長い曜日={長い曜日}、短い曜日={短い曜日}");
// 出力:長い曜日=木曜日、短い曜日=木
// stringクラスのFormatメソッドを使う
string 長い曜日2 = string.Format("{0:dddd}", theDay);
string 短い曜日2 = string.Format("{0:ddd}", theDay);
Console.WriteLine($"長い曜日={長い曜日2}、短い曜日={短い曜日2}");
// 出力:長い曜日=木曜日、短い曜日=木
' 例:2017年10月5日 木曜日
Dim theDay = New DateTime(2017, 10, 5)
' DateTime構造体のToStringメソッドを使う
Dim 長い曜日 As String = theDay.ToString("dddd")
Dim 短い曜日 As String = theDay.ToString("ddd")
Console.WriteLine($"長い曜日={長い曜日}、短い曜日={短い曜日}")
' 出力:長い曜日=木曜日、短い曜日=木
' StringクラスのFormatメソッドを使う
Dim 長い曜日2 As String = String.Format("{0:dddd}", theDay)
Dim 短い曜日2 As String = String.Format("{0:ddd}", theDay)
Console.WriteLine($"長い曜日={長い曜日2}、短い曜日={短い曜日2}")
' 出力:長い曜日=木曜日、短い曜日=木
英語などで取得する:「Sunday」/「Sun」
日付を文字列にフォーマットするときに、カルチャーも渡せばよい。
カルチャー(ロケール)はCultureInfoクラス(System.Globalization名前空間)で表される。望みのカルチャーを指定してCultureInfoオブジェクトを作り、それを書式指定文字列とともに渡してフォーマットしてもらえばよい。ここでは曜日を英語で取得する例を示す(次のコード)。
// 例:2017年10月5日 木曜日
var theDay = new DateTime(2017, 10, 5);
// 英語のカルチャー
var culture = System.Globalization.CultureInfo.GetCultureInfo("en-US");
// DateTime構造体のToStringメソッドを使う
string longDayOfTheWeek = theDay.ToString("dddd", culture);
string shortDayOfTheWeek = theDay.ToString("ddd", culture);
Console.WriteLine($"長い曜日={longDayOfTheWeek}、短い曜日={shortDayOfTheWeek}");
// 出力:長い曜日=Thursday、短い曜日=Thu
// stringクラスのFormatメソッドを使う
string longDayOfTheWeek2 = string.Format(culture, "{0:dddd}", theDay);
string shortDayOfTheWeek2 = string.Format(culture, "{0:ddd}", theDay);
Console.WriteLine($"長い曜日={longDayOfTheWeek2}、短い曜日={shortDayOfTheWeek2}");
// 出力:長い曜日=Thursday、短い曜日=Thu
' 例:2017年10月5日 木曜日
Dim theDay = New DateTime(2017, 10, 5)
' 英語のカルチャー
Dim culture = System.Globalization.CultureInfo.GetCultureInfo("en-US")
' DateTime構造体のToStringメソッドを使う
Dim longDayOfTheWeek As String = theDay.ToString("dddd", culture)
Dim shortDayOfTheWeek As String = theDay.ToString("ddd", culture)
Console.WriteLine($"長い曜日={longDayOfTheWeek}、短い曜日={shortDayOfTheWeek}")
' 出力:長い曜日=Thursday、短い曜日=Thu
' StringクラスのFormatメソッドを使う
Dim longDayOfTheWeek2 As String = String.Format(culture, "{0:dddd}", theDay)
Dim shortDayOfTheWeek2 As String = String.Format(culture, "{0:ddd}", theDay)
Console.WriteLine($"長い曜日={longDayOfTheWeek2}、短い曜日={shortDayOfTheWeek2}")
' 出力:長い曜日=Thursday、短い曜日=Thu
カルチャーを指定する文字列(「en-US」や「ja-JP」など)の一覧は、MSDNの「[MS-LCID]: Windows Language Code Identifier (LCID) Reference」の中の「5 Appendix A: Product Behavior」を参照。
独自の略称を使う
曜日の略称として独自の文字列を使いたいことがある。例えば、日曜日は「Su」、月曜日は「M」などと1〜2文字のアルファベットで表示したいというような場合だ。
このようなときは、日付から曜日を表す数値(あるいは列挙値)を取得し、それを使って配列を参照するなどして独自の文字列を得る(次のコード)。DateTime構造体のDayOfWeekプロパティでは、System名前空間のDayOfWeek列挙体(元になる整数は0〜6)が得られる。Visual Basicでは、Weekday関数を使って1〜7の整数を得ることもできる。
string[] 曜日名配列 = { "Su", "M", "Tu", "W", "Th", "F", "Sa", };
// 例:2017年10月5日 木曜日
var theDay = new DateTime(2017, 10, 5);
// DayOfWeekを使う
DayOfWeek dow = theDay.DayOfWeek; // 日曜=0〜土曜=6
string 独自の曜日名 = 曜日名配列[(int)dow];
Console.WriteLine($"独自の曜日名={独自の曜日名}");
// 出力:独自の曜日名=Th
Dim 曜日名配列 As String() = {"Su", "M", "Tu", "W", "Th", "F", "Sa"}
' 例:2017年10月5日 木曜日
Dim theDay = New DateTime(2017, 10, 5)
' DayOfWeekを使う
Dim dow As DayOfWeek = theDay.DayOfWeek ' 日曜=0〜土曜=6
Dim 独自の曜日名 As String = 曜日名配列(dow)
Console.WriteLine($"独自の曜日名={独自の曜日名}")
' 出力:独自の曜日名=Th
' Weekday関数を使う
Dim wd As Integer = Weekday(theDay) ' 日曜=1〜土曜=7
Dim 独自の曜日名2 As String = 曜日名配列(wd - 1)
Console.WriteLine($"独自の曜日名(Weekday関数使用)={独自の曜日名2}")
' 出力:独自の曜日名(Weekday関数使用)=Th
六曜(大安や仏滅など)
六曜(大安/赤口/先勝/友引/先負/仏滅)は、旧暦(天保歴)の月日から求められる。月と日の数字を足して6で割った余りが0なら大安、余りが1なら赤口……などとなる(そのため、旧暦の月末と翌月1日とでは六曜が連続しないこともある)。
旧暦の月日はJapaneseLunisolarCalendarクラス(System.Globalization名前空間)で求められる(Lunisolar Calendar=太陰太陽暦)。ただし、旧暦には閏月がある(例えば2017年には5月と6月の間に閏月があり、「閏5月」と呼ぶ)。六曜を正しく求めるには、閏月もきちんと処理しなければならない(次のコード)。
// 太陰太陽暦を使って六曜を求める
string[] 六曜名配列 = { "大安", "赤口", "先勝", "友引", "先負", "仏滅", };
// 例:2017年10月5日 木曜日(大安)
var theDay = new DateTime(2017, 10, 5);
var 旧暦 = new System.Globalization.JapaneseLunisolarCalendar();
int 旧暦の月 = 旧暦.GetMonth(theDay);
int 旧暦の日 = 旧暦.GetDayOfMonth(theDay);
// 閏月を取得
DateTime 旧暦元日 = 旧暦.AddDays(theDay, 1 - 旧暦.GetDayOfYear(theDay));
int 閏月 = 旧暦.GetLeapMonth(旧暦.GetYear(旧暦元日), 旧暦.GetEra(旧暦元日));
// 2017年であれば、閏月=6 が返る。6番目の月が閏月、すなわち「閏5月」となる。
// 閏月のない年では、閏月=0 が返る。
// 閏月がある場合の旧暦月の補正
if ((閏月 > 0) && (旧暦の月 >= 閏月))
旧暦の月--;
// 六曜を算出
string 六曜 = 六曜名配列[(旧暦の月 + 旧暦の日) % 6];
Console.Write($"{theDay:yyyy年M月d日}は");
Console.WriteLine($"旧暦{旧暦の月}月{旧暦の日}日({六曜})");
// 出力:2017年10月5日は旧暦8月16日(大安)
' 太陰太陽暦を使って六曜を求める
Dim 六曜名配列 As String() = {"大安", "赤口", "先勝", "友引", "先負", "仏滅"}
' 例:2017年10月5日 木曜日
Dim theDay = New DateTime(2017, 10, 5)
Dim 旧暦 = New System.Globalization.JapaneseLunisolarCalendar()
Dim 旧暦の月 As Integer = 旧暦.GetMonth(theDay)
Dim 旧暦の日 As Integer = 旧暦.GetDayOfMonth(theDay)
' 閏月を取得
Dim 旧暦元日 As DateTime = 旧暦.AddDays(theDay, 1 - 旧暦.GetDayOfYear(theDay))
Dim 閏月 As Integer = 旧暦.GetLeapMonth(旧暦.GetYear(旧暦元日), 旧暦.GetEra(旧暦元日))
' 2017年であれば、閏月=6 が返る。6番目の月が閏月、すなわち「閏5月」となる。
' 閏月のない年では、閏月 = 0 が返る。
' 閏月がある場合の旧暦月の補正
If ((閏月 > 0) AndAlso (旧暦の月 >= 閏月)) Then
旧暦の月 -= 1
End If
' 六曜を算出
Dim 六曜 As String = 六曜名配列((旧暦の月 + 旧暦の日) Mod 6)
Console.Write($"{theDay:yyyy年M月d日}は")
Console.WriteLine($"旧暦{旧暦の月}月{旧暦の日}日({六曜})")
' 出力:2017年10月5日は旧暦8月16日(大安)
閏月を算出する際に旧暦元日を求めているが、これは以下の不具合を回避するためだ。年号が変わった直後のとある日が旧暦では前年に当たる場合、その日をGetLeapMonthメソッドに渡しても正しく動作しない。例えば、平成元年(=1989年)1月8日(旧暦では前年の12月1日)〜2月5日(旧暦では前年の12月29日=大みそか)の期間である。
なお、現在の旧暦は1844年から使われるようになったものなので、このコードはそれ以前の日付には適用できない。また、「旧暦2033年問題」があり、それ以降はこのコードでは対応できないので注意してほしい。
まとめ
曜日の文字列を得る方法は、日付を文字列にフォーマットするときに書式指定するのが基本だ。ただし、カルチャーには注意を払う必要がある。独自の表記にするには、日付から曜日を表す整数(または列挙値)を取得して利用する。また、(今後十数年で旧暦が限界を迎えてしまうようだが、少なくともそれまでは).NET Frameworkで六曜も算出できる。
利用可能バージョン:.NET Framework 1.0以降
カテゴリ:クラスライブラリ 処理対象:日付と時刻
使用ライブラリ:DateTime構造体(System名前空間)
使用ライブラリ:CultureInfoクラス(System.Globalization名前空間)
使用ライブラリ:JapaneseLunisolarCalendarクラス(System.Globalization名前空間)
関連TIPS:指定した月から特定の曜日の日付を取得するには?[C#、VB]
関連TIPS:祝日を求めるには?[C#、VB]
関連TIPS:日付の年号を略称で表示するには?[C#、VB]
関連TIPS:西暦と和暦を変換するには?
関連TIPS:日付や時刻を文字列に変換するには?
関連TIPS:数値を右詰めや0埋めで文字列化するには?[C#、VB]
■この記事と関連性の高い別の.NET TIPS
- 指定した月から特定の曜日の日付を取得するには?
- 月初/月末の日付を求めるには?[C#、VB]
- 週の始まりの日付を求めるには?
- 日付や時刻を文字列に変換するには?
- [ASP.NET AJAX]グローバリゼーション対応を行うには?
Copyright© Digital Advantage Corp. All Rights Reserved.