例えばJavaScriptで8月31日の1か月後を取得しようとして
const date = new Date('2021/08/31');
date.setMonth(date.getMonth() + 1);
としても、9月は30日までしかないので月が繰り上がり、実際に得られる日付は10月1日になってしまいますが、そのような日数の異なる月を目標月とした場合でも末日で丸めた9月30日として取得できるようにした関数です。
JavaScript/PHP版ともに、目標月+1月の0日を指定することで一旦目標月の末日にし、得られた末日と元の日付の「日」のうち小さいほうで「日」を再設定することで求めたい日付を取得しています。
JavaScript版####
function addMonth(date, num) {
const d = new Date(date);
d.setMonth(d.getMonth() + num + 1, 0);
d.setDate(Math.min(d.getDate(), date.getDate()));
return d;
}
// sample
const baseDate = new Date('2021/08/31');
console.log('base date :', baseDate.toLocaleDateString('ja'), "\n");
for(let i = -12; i <= 12; i++) {
const r = addMonth(baseDate, i);
console.log('%s month : %s',
`${(i < 0 ? i : `+${i}`)}`.padStart(3), r.toLocaleDateString('ja'));
}
/*
base date : 2021/8/31
-12 month : 2020/8/31
-11 month : 2020/9/30
-10 month : 2020/10/31
-9 month : 2020/11/30
-8 month : 2020/12/31
-7 month : 2021/1/31
-6 month : 2021/2/28
-5 month : 2021/3/31
-4 month : 2021/4/30
-3 month : 2021/5/31
-2 month : 2021/6/30
-1 month : 2021/7/31
+0 month : 2021/8/31
+1 month : 2021/9/30
+2 month : 2021/10/31
+3 month : 2021/11/30
+4 month : 2021/12/31
+5 month : 2022/1/31
+6 month : 2022/2/28
+7 month : 2022/3/31
+8 month : 2022/4/30
+9 month : 2022/5/31
+10 month : 2022/6/30
+11 month : 2022/7/31
+12 month : 2022/8/31
*/
PHP版####
<?php
function addMonth($date, $num) {
$d = (new DateTime)->setTimestamp($date->getTimestamp());
$d->setDate($d->format('Y'), $d->format('m') + $num + 1, 0)
->setDate($d->format('Y'), $d->format('m'), min($d->format('d'), $date->format('d')));
return (new DateTimeImmutable)->setTimestamp($d->getTimestamp());
}
// sample
$baseDate = (new DateTimeImmutable)->setDate(2021, 8, 31);
echo "base date : {$baseDate->format('Y-m-d')}\n\n";
for($i = -12; $i <= 12; $i++) {
$r = addMonth($baseDate, $i);
printf("%+3d month : %s\n", $i, $r->format('Y-m-d'));
}
// result
/*
base date : 2021-08-31
-12 month : 2020-08-31
-11 month : 2020-09-30
-10 month : 2020-10-31
-9 month : 2020-11-30
-8 month : 2020-12-31
-7 month : 2021-01-31
-6 month : 2021-02-28
-5 month : 2021-03-31
-4 month : 2021-04-30
-3 month : 2021-05-31
-2 month : 2021-06-30
-1 month : 2021-07-31
+0 month : 2021-08-31
+1 month : 2021-09-30
+2 month : 2021-10-31
+3 month : 2021-11-30
+4 month : 2021-12-31
+5 month : 2022-01-31
+6 month : 2022-02-28
+7 month : 2022-03-31
+8 month : 2022-04-30
+9 month : 2022-05-31
+10 month : 2022-06-30
+11 month : 2022-07-31
+12 month : 2022-08-31
*/
引き数
addMonth(日付オブジェクト, 月の増減値)
戻り値
指定した値で月を増減された日付オブジェクト
引き数チェックは入れていませんので必要に応じて追加してください。