diff --git a/src/Carbon/Traits/Date.php b/src/Carbon/Traits/Date.php index be9d24a8ed..27e1245a74 100644 --- a/src/Carbon/Traits/Date.php +++ b/src/Carbon/Traits/Date.php @@ -936,7 +936,7 @@ public function get($name) 'microsecond' => 'u', // @property int 0 (for Sunday) through 6 (for Saturday) 'dayOfWeek' => 'w', - // @property-read int 1 (for Monday) through 7 (for Sunday) + // @property int 1 (for Monday) through 7 (for Sunday) 'dayOfWeekIso' => 'N', // @property int ISO-8601 week number of year, weeks starting on Monday 'weekOfYear' => 'W', @@ -1308,6 +1308,16 @@ public function set($name, $value = null) break; + case 'dayOfWeek': + $this->addDays($value - $this->dayOfWeek); + + break; + + case 'dayOfWeekIso': + $this->addDays($value - $this->dayOfWeekIso); + + break; + case 'timestamp': $this->setTimestamp($value); @@ -1349,7 +1359,7 @@ public function set($name, $value = null) ], true) ? 1 : 0) + (int) floor($start->diffInUnit($firstUnit, $this)); // We check $value a posteriori to give precedence to UnknownUnitException - if (!is_int($value)) { + if (!\is_int($value)) { throw new UnitException("->$name expects integer value"); } @@ -1446,9 +1456,15 @@ public function getTranslatedShortMonthName($context = null) /** * Get/set the day of year. * + * @template T of int|null + * * @param int|null $value new value for day of year if using as setter. * + * @psalm-param T $value + * * @return static|int + * + * @psalm-return (T is int ? static : int) */ public function dayOfYear($value = null) { @@ -2763,6 +2779,22 @@ public function __call($method, $parameters) } } + if (preg_match('/^([a-z]{2,})(In|Of)([A-Z][a-z]+)$/', $method, $match)) { + $value = null; + + try { + $value = isset($parameters[0]) + ? $this->set($method, $parameters[0]) + : $this->get($method); + } catch (UnknownGetterException|UnknownSetterException) { + // continue to macro + } + + if ($value !== null) { + return $value; + } + } + return static::bindMacroContext($this, function () use (&$method, &$parameters) { $macro = $this->getLocalMacro($method); diff --git a/tests/Carbon/SettersTest.php b/tests/Carbon/SettersTest.php index d0b7e31ba6..ffcf2aa58d 100644 --- a/tests/Carbon/SettersTest.php +++ b/tests/Carbon/SettersTest.php @@ -13,6 +13,7 @@ namespace Tests\Carbon; +use BadMethodCallException; use Carbon\Carbon; use Carbon\Exceptions\UnitException; use DateTimeZone; @@ -129,10 +130,52 @@ public function testSecondSetter() public function testUnitOfUnit() { - $date = Carbon::create(2018, 1, 27, 20, 12, 42, 'America/Toronto'); + $date = Carbon::create(2023, 1, 27, 20, 12, 42, 'America/Toronto'); $date->minuteOfYear = (95 * 24 + 3) * 60 + 50; - $this->assertSame('2018-04-06 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + $this->assertSame('2023-04-06 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + + $date->dayOfWeek = 2; + + $this->assertSame('2023-04-04 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + + $date->dayOfWeek = 6; + + $this->assertSame('2023-04-08 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + + $date->dayOfWeek = 0; + + $this->assertSame('2023-04-02 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + + $date->dayOfWeekIso = 7; + + $this->assertSame('2023-04-02 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + + $date->dayOfWeek = 4; + + $this->assertSame('2023-04-06 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + + $date->dayOfWeekIso = 7; + + $this->assertSame('2023-04-09 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + } + + public function testUnitOfUnitMethod() + { + $date = Carbon::create(2023, 1, 27, 20, 12, 42, 'America/Toronto'); + $date->minuteOfYear((95 * 24 + 3) * 60 + 50); + + $this->assertSame('2023-04-06 04:50:42 America/Toronto', $date->format('Y-m-d H:i:s e')); + } + + public function testUnitOfUnitUnknownMethod() + { + $this->expectExceptionObject(new BadMethodCallException( + 'Method fooOfBar does not exist.', + )); + + $date = Carbon::create(2023, 1, 27, 20, 12, 42, 'America/Toronto'); + $date->fooOfBar((95 * 24 + 3) * 60 + 50); } public function testUnitOfUnitFloat() diff --git a/tests/CarbonImmutable/GettersTest.php b/tests/CarbonImmutable/GettersTest.php index 81a80a9f99..76d81eb74d 100644 --- a/tests/CarbonImmutable/GettersTest.php +++ b/tests/CarbonImmutable/GettersTest.php @@ -470,6 +470,27 @@ public function testUnitOfUnit() $this->assertSame(1, $date->dayOfMinute); } + public function testUnitOfUnitMethod() + { + $date = Carbon::createFromDate(2018, 7, 6); + $this->assertSame(6, $date->dayOfQuarter()); + + $date = Carbon::createFromDate(2018, 8, 6); + $this->assertSame(6 + 31, $date->dayOfQuarter()); + + $date = Carbon::create(2018, 4, 6, 4, 50, 0, 'UTC'); + $this->assertSame((95 * 24 + 4) * 60 + 50, $date->minuteOfYear()); + + $date = Carbon::create(2018, 4, 6, 4, 50, 0, 'America/Toronto'); + $this->assertSame((95 * 24 + 3) * 60 + 50, $date->minuteOfYear()); + + $date = Carbon::create(2018, 4, 6, 4, 50, 0, 'America/Toronto'); + $this->assertSame(0, $date->yearOfMinute()); + + $date = Carbon::create(2018, 4, 6, 4, 50, 0, 'America/Toronto'); + $this->assertSame(1, $date->dayOfMinute()); + } + public function testUnitInUnit() { $date = Carbon::createFromDate(2018, 7, 6);