Posted at

各言語における無効日付(2月31日など)の扱い

More than 1 year has passed since last update.

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クラスは末日をきれいに出力してくれます。