現在の日付から、その月初めの曜日を求めてみよう

こんにちはー！ニアです。
今回は現在の日付から、その月初めの曜日を求める（例：2016年2月20（土）なら、月初め（2016年2月1日）の曜日は月曜日）方法について紹介していきます。

カレンダーアプリ開発にて、月初めの日の位置を調整したい時に活用してみましょう。

#1. 日付を扱うクラスの機能で、指定した日付の曜日を取得できる場合
.NETの[DateTime](https://msdn.microsoft.com/ja-jp/library/system.datetime.aspx)構造体やJavaの[Calendar](https://docs.oracle.com/javase/jp/6/api/java/util/Calendar.html)クラスなどでは、指定した日付の曜日を取得できる機能があります。

.NETでは、[DateTime.Now](https://msdn.microsoft.com/ja-jp/library/system.datetime.now.aspx)（[Today](https://msdn.microsoft.com/ja-jp/library/system.datetime.today.aspx)でもOK）プロパティで現在の日付を取得し、[DateTime](https://msdn.microsoft.com/ja-jp/library/system.datetime.datetime.aspx)のコンストラクターでその月初めの日付を表すインスタンスを生成して、[DayOfWeek](https://msdn.microsoft.com/ja-jp/library/system.datetime.dayofweek.aspx)プロパティで取得します。

```csharp:DateTime構造体の機能を利用（C#）
using System;
// ...

// 現在の日付を取得します。
var today = DateTime.Now;
// その月初めの日付を表すインスタンスを生成します。
var firstDay = new DateTime( today.Year, today.Month, 1 );
// 以下の文でもOKです。
//var firstDay = today.AddDays( 1 - today.Day );

// 月初めの曜日を取得します。
DayOfWeek firstDate = firstDay.DayOfWeek;
```

[DayOfWeek]()は列挙体であり、以下の列挙子が定義されています。

|列挙子|値|概要|
|:---:|:---:|:---:|
|Sunday|0|日曜日|
|Monnday|1|月曜日|
|Tuesday|2|火曜日|
|Wednesday|3|水曜日|
|Thursday|4|木曜日|
|Friday|5|金曜日|
|Saturday|6|土曜日|

Javaでは、[Calendar.getInstance](https://docs.oracle.com/javase/jp/6/api/java/util/Calendar.html#getInstance())メソッドで現在の日付を取得し、[set](https://docs.oracle.com/javase/jp/6/api/java/util/Calendar.html#set(int, int))メソッドでフィードを[Calendar.DATE](https://docs.oracle.com/javase/jp/6/api/java/util/Calendar.html#DATE)を指定してその月初めの日付に設定し、[get](https://docs.oracle.com/javase/jp/6/api/java/util/Calendar.html#get(int))メソッドで[Calendar.DAY_OF_WEEK](https://docs.oracle.com/javase/jp/6/api/java/util/Calendar.html#DAY_OF_WEEK)を指定して曜日を表す値を取得します。

```java:Calendarクラスの機能を利用（Java）
import java.util.Calendar;
// ...

Calendar today = Calendar.getInstance();
Calendar firstDay = Calendar.getInstance();
firstDay.set( Calendar.DATE, 1 );
int firstDate = firstDay.get( Calendar.DAY_OF_WEEK );
```

Calendarクラスには、曜日を表すフィールドが定義されています。

|フィールド|値|概要|
|:---:|:---:|:---:|
|SUNDAY|1|日曜日|
|MONDAY|2|月曜日|
|TUESDAY|3|火曜日|
|WEDNESDAY|4|水曜日|
|THURSDAY|5|木曜日|
|FRIDAY|6|金曜日|
|SATURDAY|7|土曜日|



#2. 現在の年月日が分かる場合

現在の年月日が分かる場合、**[Zellerの公式](https://ja.wikipedia.org/wiki/%E3%83%84%E3%82%A7%E3%83%A9%E3%83%BC%E3%81%AE%E5%85%AC%E5%BC%8F)**（式(1)）を使って求めます。

$w = y + \lfloor y/4 \rfloor + \lfloor y/400 \rfloor - \lfloor y/100 \rfloor + ( ( 13 * m + 8 ) / 5 + d ) \mod 7 \tag{1}$

※但し、$w$ : 曜日 / $y$ : 年 / $m$ : 月 / $d$ : 日

|$w$の値|曜日|
|:---:|:---:|
|0|日曜日|
|1|月曜日|
|2|火曜日|
|3|水曜日|
|4|木曜日|
|5|金曜日|
|6|土曜日|

```csharp:Zellerの公式（C#）
using System;
// ...

// 現在の日付を取得します。
var today = DateTime.Now;

// 月初めの曜日を取得します。
int w = today.Year / 4 + today.Year / 400 - today.Year / 100 +
		( ( 13 * today.Month + 8 ) / 5 + 1 ) % 7;

```

#3. 現在の日とその曜日が分かる場合

現在の日とその曜日が分かる場合、以下に示す式(2)から月初めの曜日を求めることができます。

$w_1 = ( w_d + 7 - ( d - 1 ) \mod 7 ) \mod 7 \tag{2}$

※但し、$w_1$ : 月初めの曜日 / $d$ : 現在日 / $w_d$ : 現在日の曜日

上記の式は「**現在日（d日とします）の曜日**」の値（$w_d$）と「**月初めの日を日曜日とした時の、d日の曜日**」の値（$( d - 1 ) \mod 7$）との差を求めて、月初めの曜日を算出しています。

|$w_1$、$w_d$の値|曜日|
|:---:|:---:|
|0|日曜日|
|1|月曜日|
|2|火曜日|
|3|水曜日|
|4|木曜日|
|5|金曜日|
|6|土曜日|

```csharp:式(2)の方法（C#）
using System;
// ...

// 現在の日付を取得します。
var today = DateTime.Now;

// 月初めの曜日を取得します。
int w = ( ( int )today.DayOfWeek + 7 - ( today.Day - 1 ) % 7 ) % 7;
```

##【裏話】3.の式(2)ができるまで
実物のカレンダーをじっと見つめていた時、「現在日とその曜日と7の余剰を組み合わせれば、月初めの曜日が求められそう」というアイディアがふと思いつき、試しに式を組み立ててみました。

それでは、See you next!