diff --git a/composer.json b/composer.json index c701831..33c66fe 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "ext-mbstring": "*", "ext-json": "*", "justinrainbow/json-schema": "^5.2.10", - "nesbot/carbon": "^2.63.0", + "nesbot/carbon": "^2.63.0 || ^3.0", "jmikola/geojson": "^1.0" }, "require-dev": { diff --git a/src/Fields/DateField.php b/src/Fields/DateField.php index 6e1be82..0284c06 100644 --- a/src/Fields/DateField.php +++ b/src/Fields/DateField.php @@ -11,6 +11,10 @@ class DateField extends BaseField protected function validateCastValue($val) { + if (!is_string($val) && !$val instanceof \DateTimeInterface) { + throw $this->getValidationException('must be string or datetime', $val); + } + if ('any' === $this->format()) { try { $date = new Carbon($val); diff --git a/src/Fields/DatetimeField.php b/src/Fields/DatetimeField.php index 5b10bda..60a0f27 100644 --- a/src/Fields/DatetimeField.php +++ b/src/Fields/DatetimeField.php @@ -9,6 +9,10 @@ class DatetimeField extends BaseField { protected function validateCastValue($val) { + if (!is_string($val) && !$val instanceof \DateTimeInterface) { + throw $this->getValidationException('must be string or datetime', $val); + } + $val = trim($val); switch ($this->format()) { case 'default': diff --git a/src/Fields/TimeField.php b/src/Fields/TimeField.php index 9a50578..6fc4dbd 100644 --- a/src/Fields/TimeField.php +++ b/src/Fields/TimeField.php @@ -13,6 +13,10 @@ class TimeField extends BaseField { protected function validateCastValue($val) { + if (!is_string($val) && !$val instanceof \DateTimeInterface) { + throw $this->getValidationException('must be string or datetime', $val); + } + switch ($this->format()) { case 'default': $time = explode(':', $val); diff --git a/tests/FieldTypesTest.php b/tests/FieldTypesTest.php index 75399bc..ff34317 100644 --- a/tests/FieldTypesTest.php +++ b/tests/FieldTypesTest.php @@ -579,7 +579,14 @@ protected function assertFieldTestData($fieldType, $testData): void if (self::ERROR === $expectedCastValue) { $this->assertNotEmpty($field->validateValue($inputValue), $assertMessage); } elseif (is_object($expectedCastValue)) { - $this->assertEquals($expectedCastValue, $field->castValue($inputValue), $assertMessage); + $castValue = $field->castValue($inputValue); + if ($expectedCastValue instanceof CarbonInterval && $castValue instanceof CarbonInterval) { + // Carbon 3.x changed internal CarbonInterval properties (e.g. originalInput), + // breaking whole-object comparison. Compare the ISO 8601 spec instead. + $this->assertEquals($expectedCastValue->spec(), $castValue->spec(), $assertMessage); + } else { + $this->assertEquals($expectedCastValue, $castValue, $assertMessage); + } } else { $this->assertSame($expectedCastValue, $field->castValue($inputValue), $assertMessage); }