diff --git a/NEWS b/NEWS index d6e5c03d3314..4d0f0ae5907c 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ PHP NEWS - Date: . Fix unserialization of Time\Duration. (timwolla) + . Add comparison handler for Time\Duration. (timwolla) - DOM: . Fixed use-after-free when re-constructing a DOMXPath whose php:function diff --git a/ext/date/php_time.c b/ext/date/php_time.c index 2c3698f63fbd..41f2673eafe7 100644 --- a/ext/date/php_time.c +++ b/ext/date/php_time.c @@ -48,6 +48,13 @@ static zend_object *time_duration_object_clone(zend_object *object) return &new_obj->std; } +static int time_duration_object_compare(zval *a, zval *b) +{ + ZEND_COMPARE_OBJECTS_FALLBACK(a, b); + + return timelib_duration_compare(&Z_DATE_TIME_DURATION_P(a)->duration, &Z_DATE_TIME_DURATION_P(b)->duration); +} + PHP_MINIT_FUNCTION(date_time) { /* Time\TimeException */ @@ -57,6 +64,7 @@ PHP_MINIT_FUNCTION(date_time) memcpy(&time_duration_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); time_duration_object_handlers.offset = offsetof(php_date_time_duration, std); time_duration_object_handlers.clone_obj = time_duration_object_clone; + time_duration_object_handlers.compare = time_duration_object_compare; php_date_ce_time_duration = register_class_Time_Duration(); php_date_ce_time_duration->create_object = time_duration_object_create; php_date_ce_time_duration->default_object_handlers = &time_duration_object_handlers; diff --git a/ext/date/tests/time/duration/compare.phpt b/ext/date/tests/time/duration/compare.phpt new file mode 100644 index 000000000000..fd0f5d9002c9 --- /dev/null +++ b/ext/date/tests/time/duration/compare.phpt @@ -0,0 +1,49 @@ +--TEST-- +Time\Duration: Comparison handlers +--FILE-- +')); +} + +$durations = [ + ...$durations, + null, + ...negate_all($durations), +]; + +foreach ($durations as $a) { + if ($a === null) { + continue; + } + + foreach ($durations as $b) { + if ($b === null) { + continue; + } + + if (n($a <=> $b) !== n(Time\Duration::compare($a, $b))) { + echo sprintf('%1$s <=> %2$s !== Duration::compare(%1$s, %2$s)', f($a, pad: false), f($b, pad: false)), PHP_EOL; + } + } +} + +?> +==DONE== +--EXPECT-- +==DONE==