Skip to content

Implement DateTime Exceptions RFC #10366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ PHP NEWS
(ilutov)
. Fix bug GH-10083 (Allow comments between & and parameter). (ilutov)

- Date:
. Implement More Appropriate Date/Time Exceptions RFC. (Derick)

- Exif:
. Removed unneeded codepaths in exif_process_TIFF_in_JPEG(). (nielsdos)

Expand Down
292 changes: 213 additions & 79 deletions ext/date/php_date.c

Large diffs are not rendered by default.

66 changes: 63 additions & 3 deletions ext/date/php_date.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,6 @@ public function format(string $format): string {}

/**
* @tentative-return-type
* @alias date_modify
*/
public function modify(string $modifier): DateTime|false {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @derickr, looking at https://3v4l.org/iSPL9,
it doesn't seem possible for

Datetime::modify
DatetimeImmutable::modify
DateInterval::createFromDateString

to return false anymore.

Shouldn't the stub be updated then ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@VincentLanglet Good catch, I've just filed #14600 fixing these return types.


Expand All @@ -389,7 +388,6 @@ public function add(DateInterval $interval): DateTime {}

/**
* @tentative-return-type
* @alias date_sub
*/
public function sub(DateInterval $interval): DateTime {}

Expand Down Expand Up @@ -668,7 +666,6 @@ public function __construct(string $duration) {}

/**
* @tentative-return-type
* @alias date_interval_create_from_date_string
*/
public static function createFromDateString(string $datetime): DateInterval|false {}

Expand Down Expand Up @@ -749,3 +746,66 @@ public static function __set_state(array $array): DatePeriod {}

public function getIterator(): Iterator {}
}

/**
* @strict-properties
*/
class DateError extends Error
{
}

/**
* @strict-properties
*/
class DateObjectError extends DateError
{
}

/**
* @strict-properties
*/
class DateRangeError extends DateRangeError
{
}

/**
* @strict-properties
*/
class DateException extends Exception
{
}

/**
* @strict-properties
*/
class DateInvalidTimeZoneException extends Exception
{
}

/**
* @strict-properties
*/
class DateInvalidOperationException extends DateException
{
}

/**
* @strict-properties
*/
class DateMalformedStringException extends DateException
{
}

/**
* @strict-properties
*/
class DateMalformedIntervalStringException extends DateException
{
}

/**
* @strict-properties
*/
class DateMalformedPeriodStringException extends DateException
{
}
155 changes: 151 additions & 4 deletions ext/date/php_date_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ext/date/tests/68062.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ echo $tz->getOffset($dt), "\n";
try {
echo $tz->getOffset(1);
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
echo $e::class, ': ', $e->getMessage(), "\n";
}
?>
--EXPECT--
3600
DateTimeZone::getOffset(): Argument #1 ($datetime) must be of type DateTimeInterface, int given
TypeError: DateTimeZone::getOffset(): Argument #1 ($datetime) must be of type DateTimeInterface, int given
21 changes: 21 additions & 0 deletions ext/date/tests/DateInterval_construct_exceptions.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
DateInterval constructor exceptions
--INI--
date.timezone=Europe/London
--FILE--
<?php
function check(callable $c)
{
try {
var_dump($c());
} catch (\DateMalformedIntervalStringException $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
}
}

check(fn() => new DateInterval(""));
check(fn() => new DateInterval("2007-05-11T15:30:00Z/"));
?>
--EXPECTF--
DateMalformedIntervalStringException: Unknown or bad format ()
DateMalformedIntervalStringException: Failed to parse interval (2007-05-11T15:30:00Z/)
12 changes: 12 additions & 0 deletions ext/date/tests/DateInterval_createFromDateString_broken.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
Test DateInterval::createFromDateString() function : nonsense data
--FILE--
<?php
try {
$i = DateInterval::createFromDateString("foobar");
} catch (DateMalformedIntervalStringException $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
}
?>
--EXPECTF--
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this can now be EXPECT instead of EXPECTF :)

DateMalformedIntervalStringException: Unknown or bad format (foobar) at position 0 (f): The timezone could not be found in the database
17 changes: 6 additions & 11 deletions ext/date/tests/DateInterval_serialize-003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ var_dump($d);
echo "\n\nUsed serialised interval:\n";
$now = new DateTimeImmutable("2022-04-22 16:25:11 BST");
var_dump($now->add($e));
var_dump($now->sub($e));
try {
var_dump($now->sub($e));
} catch (DateInvalidOperationException $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
}
?>
--EXPECTF--
Original object:
Expand Down Expand Up @@ -84,13 +88,4 @@ object(DateTimeImmutable)#4 (3) {
["timezone"]=>
string(3) "BST"
}

Warning: DateTimeImmutable::sub(): Only non-special relative time specifications are supported for subtraction in %s on line %d
object(DateTimeImmutable)#4 (3) {
["date"]=>
string(26) "2022-04-22 16:25:11.000000"
["timezone_type"]=>
int(2)
["timezone"]=>
string(3) "BST"
}
DateInvalidOperationException: DateTimeImmutable::sub(): Only non-special relative time specifications are supported for subtraction
22 changes: 22 additions & 0 deletions ext/date/tests/DateInterval_set_state_exception.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
DateInterval invalid serialization data with date_string
--FILE--
<?php
$propertySets = [
'2023-01-16 17:01:19',
'2023-01-16-foobar$*',
];

foreach( $propertySets as $propertySet )
{
try {
$d = DateInterval::__set_state( [ 'date_string' => $propertySet ] );
echo "OK\n";
} catch (\Error $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
}
}
?>
--EXPECT--
OK
Error: Unknown or bad format (2023-01-16-foobar$*) at position 10 (-) while unserializing: Unexpected character
Loading