様々な言語で月末の日付を求める（C#,Java,Ruby,Javascript,VBA,Excel,MySQL,SQLite3,Oracle）

# はじめに

業務用のシステムやツールの開発をしていると、例えば「請求書中の請求日」や「締め処理の実行日」などで、月末日が必要になることが時々あります。
そこで、様々な言語で月末の日付を求める代表的な方法を調べてみました。

# C# 

* DateTime構造体のDaysInMonthメソッドを使って「その月の日数」を求めて、次に求めた日数を使ってDateTimeオブジェクトを生成して、月末日を求めます。
* 【余談】[公式API](https://docs.microsoft.com/ja-jp/dotnet/api/system.datetime?view=netframework-4.8)を見ると「DateTime Struct」と書かれているので、DateTimeクラスではなくDateTime構造体と呼ぶのが正確な表現だと思われます。
 
```c#:LastDayOfMonth.cs
public class LastDayOfMonth
{
    public static void CalcLastDayOfMonth()
    {
        DateTime today = DateTime.Now;
        int days = DateTime.DaysInMonth(today.Year, today.Month);
        System.Console.WriteLine(new DateTime(today.Year, today.Month, days).ToString("yyyy-MM-dd"));
    }
}
```

# Java

* Java8以降であれば、YearMonthクラスを使って月末日を直接求められます。
 * 現在日を基準にしたい時は`YearMonth.now()`、任意の年月を指定したい時は`YearMonth.of(int year, int month)`を使います。
 * LocalDateクラスを使う方法もありますが、YearMonthクラスを使う方が短くてスッキリ書けます。
 * @swordone さん、ご指摘ありがとうございます。
* Java7の場合、Calendarクラスを使ってゴニョゴニョと処理を書く必要があります。 
 * 参考URL：[Javaで日時を扱う（Java7まで）](https://qiita.com/kurukurupapa@github/items/b52dee4935a6434d006b)

```java:LastDayOfMonth.java
import java.time.LocalDate;
import java.time.YearMonth;

public class LastDayOfMonth {
	public static void main(String[] args) {
		LocalDate lastDay = YearMonth.now().atEndOfMonth();
		System.out.println(lastDay.toString());
	}
}

```

# Ruby

* Dateクラスのコンストラクタの第3引数に負の値（-1）を指定して、月末日を求めます。

```ruby:irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> today = Date.today
=> #<Date: 4917313/2,0,2299161>
irb(main):003:0> puts Date.new(today.year, today.month, -1)
2019-06-30
=> nil
```

# Javascript

* Dateクラスのコンストラクタで「任意の月の翌月の0日」を指定して、月末日を求めます。

```javascript
var today = new Date();
var last_day = new Date(today.getFullYear(), today.getMonth() + 1, 0);
document.write(last_day);
```

# VBA

* DateSerial関数で「任意の月の翌月の0日」を指定して、月末日を求めます。

```vb:Module1
Public Sub PrintLastDayOfMonth()
  Debug.print DateSerial(Year(Now()), Month(Now())+1, 0)
End Sub
```
# Excel（ワークシート関数）

* DATE関数を使用する場合、「任意の月の翌月の0日」を指定して月末日を求めます。
 * 以下の式をセルに埋め込めば、今月の月末日を求められます。
* EOMONTH関数を使用する場合は、「任意の月の0日」を指定して月末日を求めます。
 * DATE関数（翌月）とEOMONTH関数（当月）で指定する月が異なっています。
 * "EOMONTH"とは、"End Of Month"の略語だと思われます。

```vb
=DATE(YEAR(NOW()),MONTH(NOW())+1,0)

=EOMONTH(NOW(),0)
```

# MySQL

* LAST_DAY関数に「任意の日付」を指定して、月末日を求めます。
* 以下の例ではNOW関数で現在日時を指定していますが、例えば'2019-06-22'など日付文字列を引数に渡すこともできます。

```sql
mysql> SELECT LAST_DAY(NOW());
+-----------------+
| LAST_DAY(NOW()) |
+-----------------+
| 2019-06-30      |
+-----------------+
1 row in set (0.00 sec)
```

# SQLite3

* date関数に「任意の日付の翌月の初日の1日前」を指定して、月末日を求めます。
 * 任意の日付として、'now'で現在日を指定した後...
 * '+1 months'で翌月、'start of month'で月の初日、さらに'-1 days'で1日前に日付をずらしています。

```
sqlite> select date('now', '+1 months', 'start of month', '-1 days');
2019-06-30
```

# Oracle

* LAST_DAY関数に「任意の日付」を指定して、月末日を求めます。
* 以下の例ではSYSDATEで現在日時を指定していますが、例えば`TO_DATE('2020/02/19', 'YYYY/MM/DD')`などの日付を引数に渡すこともできます。

```
SELECT LAST_DAY(SYSDATE) FROM DUAL;

LAST_DAY(SYSDATE)
-----------------
29-FEB-20
```

# まとめ

* 「2019年6月35日」など、存在しない大きな日付を入れて月末日を取得する処理がありそうな気がしましたが、探した限りでは見当たりませんでした。
* MySQLやOracleの"LAST_DAY"は直感的。
 * 関数の名前が"月末日"な点も、とても分かりやすいと感じました。
* ExcelのEOMONTH関数も非常にシンプル。
 * 「Excelは機能が乏しくて、月末日を求めるのも大変だろうな...」と予想していましたが、見事に裏切られました。
* SQLite3は~~変態的~~変わり種。
 * date関数は引数が4つも必要な上、自然文のような引数を渡さなければいけません。

|言語|使用するクラス/メソッド/関数|月末日の求め方|
|---|---|---|
|C#|DateTime|「任意の年月」と「その年月における"月の日数"」を指定する。|
|Java（Java8～）|YearMonth|「任意の日付」を指定する。|
|Ruby|Date|「任意の年月の-1日」を指定する。|
|Javascript|Date|「任意の年月の翌月の0日」を指定する。|
|VBA|DateSerial|「任意の年月の翌月の0日」を指定する。|
|Excel（ワークシート関数）|DATE|「任意の年月の翌月の0日」を指定する。|
|Excel（ワークシート関数）|EOMONTH|「任意の年月の0日」を指定する。|
|MySQL|LAST_DAY|「任意の日付」を指定する。|
|SQLite3|date|「任意の日付の翌月の初日の1日前」を指定する。|
|Oracle|LAST_DAY|「任意の日付」を指定する。|


# 参考URL

* C#
 * [月初／月末の日付を求めるには？［C#、VB］](https://www.atmarkit.co.jp/ait/articles/1505/27/news018.html)
 * [C#のDateTime型に月初日や月末日を取得するメソッドを追加する](https://qiita.com/tricogimmick/items/ac95317117477958699d)
* Java
 * [Date-Time APIで月末を取得する。](http://java-beginner.com/date-time-api-lastday-of-month/)
 * ~~[[Java]LocalDate で末日取得](http://www.atroom.info/article/81)~~
* Ruby
 * [[Ruby]月末の日付を取得する](https://qiita.com/wada811/items/774afd371c4257ab613e)
* Javascript
 * [JavaScriptで月末日を取得する](https://qiita.com/akase244/items/f558b9b3c51804103d16)
* VBA
 * [今月/前月/翌月の月末日を取得する](https://www.moug.net/tech/acvba/0120017.html)
* Excel（ワークシート関数）
 * [この月の月末は何日？DATE関数で月末日を求める](https://www.becoolusers.com/excel/date-end-of-month.html)
 * [月末日付の求め方・EOMONTH 関数](https://www.excellovers.com/entry/2017/09/02/141413)
* MySQL
 * [月末の日付を取得する](http://mysql.javarou.com/dat/000849.html)
* SQLite3
 * [日付と時刻を取得する(date関数, time関数, datetime関数, julianday関数, strftime関数)](https://www.dbonline.jp/sqlite/function/index6.html)
* Oracle
 * [月末の日付を求める、その月の同月、同時刻の末日日付を求める](https://www.shift-the-oracle.com/sql/functions/last_day.html)