(new Carbon('2017-03-29'))->subMonths(0)->toDateString();
//2017-03-29
(new Carbon('2017-03-29'))->subMonths(1)->toDateString();
//2017-03-01
(new Carbon('2017-03-29'))->subMonths(2)->toDateString();
//2017-01-29
(new Carbon('2017-03-29'))->subMonthsNoOverflow(0)->toDateString();
//2017-03-29
(new Carbon('2017-03-29'))->subMonthsNoOverflow(1)->toDateString();
//2017-02-28
(new Carbon('2017-03-29'))->subMonthsNoOverflow(2)->toDateString();
//2017-01-29
月末にしか気付きにくいこんな罠が…。
subMonthsNoOverflow()を使っていけばいい。
addMonthsNoOverflow()も同じ。
というかsubMonthsはaddMonthsに飛ばしてるだけだった。
/**
* Remove months with no overflow from the instance
*
* @param int $value
*
* @return static
*/
public function subMonthsNoOverflow($value)
{
return $this->addMonthsNoOverflow(-1 * $value);
}
もしくは Carbon::useMonthsOverflow(true)
でもいいかも。
/**
* Indicates if months should be calculated with overflow.
*
* @param bool $monthsOverflow
*
* @return void
*/
public static function useMonthsOverflow($monthsOverflow = true)
{
static::$monthsOverflow = $monthsOverflow;
}
ソース見ていくとこれもしかしてPHPのDateTimeクラスの仕様?
ChronosではデフォルトでNoOverflowの動作。
https://github.com/cakephp/chronos
ImmutableではないCarbonはうっかり間違えることもあるのでChronosに切り替えるのもありかも…。
Laravelが使ってる分の影響は別にないので自分でCarbon::now()してる所を変えればいい。