2月31日などの無効な日付を各言語でどう扱うかをまとめてみた。
#PHP
<?php
$target_date = "2017-01-31";
for ($i=0; $i < 6; $i++) {
echo date('Y-m-d', strtotime($target_date . '+' . $i . ' month')) . "\n";
}
?>
2017-01-31
2017-03-03
2017-03-31
2017-05-01
2017-05-31
2017-07-01
PHPのstrtotime()では2017-01-31の1ヶ月後は「2017-02-31」となり、
「2017-02-31」は「2017-03-03」として解釈される。
#JavaScript
var date = new Date(2017 ,1 - 1, 31);
for (var i=0; i < 6; i++) {
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
console.log(year + '-' + month + '-' + day);
// 月を1ずつ増加させます
date.setMonth(date.getMonth() + 1);
}
2017-1-31
2017-3-3
2017-4-3
2017-5-3
2017-6-3
2017-7-3
JavaScriptのDateクラスの場合もPHPと同様、2017-01-31の1ヶ月後は「2017-02-31」となり、
「2017-02-31」は「2017-03-03」として解釈される。
setMonth()は破壊的メソッドのため、2017-3-3以降はずっと3日のままとなる。
#Java
import java.util.Calendar;
import java.text.SimpleDateFormat;
public class Main {
public static void main(String[] args) throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.set(2017, 1 - 1, 31);
// 表示用フォーマットを設定します
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
// 月を1ずつ増加させます
for (int i = 0 ; i < 6 ; i++){
System.out.println(sdf1.format(calendar.getTime()));
calendar.add(Calendar.MONTH, 1);
}
}
}
2017-01-31
2017-02-28
2017-03-28
2017-04-28
2017-05-28
2017-06-28
JavaのCalendarクラスの場合、増加後の月が28日までしか無い場合などは日も28に変更されます。
その後に31日まである月になったとしても日は28日のままです。
#Ruby
require "date"
date = Date.new(2017, 1 ,31)
for i in 0..5
puts((date >> i).strftime("%Y-%m-%d"))
end
2017-01-31
2017-02-28
2017-03-31
2017-04-30
2017-05-31
2017-06-30
RubyのDateクラスは末日をきれいに出力してくれます。