The comparison of two DrupalDateTime object instances using relational operators in PHP 7.3 does not produce the same result as two regular DateTime object instances in some circumstances. See the following example:
use Drupal\Core\Datetime\DrupalDateTime;
$dt_now = new DateTime();
$dt_past = new DateTime('-1 day');
$ddt_now = new DrupalDateTime();
$ddt_past = new DrupalDateTime('-1 day');
var_export($dt_past->format('F a')); // "May pm"
var_export($dt_now < $dt_past); // false
var_export($dt_now->format('c')); // 2019-05-29T15:43:02-04:00
var_export($dt_past->format('c')); // 2019-05-28T15:43:02-04:00
var_export($ddt_past->format('F a')); // "May pm"
var_export($ddt_now < $ddt_past); // true
var_export($ddt_now->format('c')); // 2019-05-29T15:43:02-04:00
var_export($ddt_past->format('c')); // 2019-05-28T15:43:02-04:00
In PHP 7.3, the relative comparison of user-defined objects results in the recursive, short-circuit comparison of each instance property's value (see this link). Considering this information, it logically follows that $ddt_past->format('F a') should then cause $ddt_now->formatTranslationCache[] to alter how the $ddt_past object instance is compared with other instances of the same type.
Ideally, DrupalDateTime (and DateTimePlus) should behave identically to DateTime with respect to the use of relational operators to compare two object instances.
Comments
Comment #2
clayfreemanComment #3
clayfreemanThe attached patch adds a test case for
DrupalDateTimeto further demonstrate the issue's testing criteria and is intended to fail for this bug.Comment #4
clayfreemanFix patch prefix so that it can be applied correctly.
Comment #5
jonathanshawComment #6
ivanhelguera commentedI have a situation when comapring DateTimePlus to DrupalDateTime always yields False. Fine with two DateTimePlus objects.
Comment #7
andypostComment #9
neclimdulBeing as this is a failure in all versions or php testbot tests this is just the way PHP behaves right? I'm not clear on a compatibility change in 7.3 that would cause this.
I'm also not really sure how we could change the operator behavior since PHP doesn't allow operator overloading. What's the critical break here we need to come up with a solution to? Maybe methods or some helper object to help comparing dates. That's what Carbon does. https://carbon.nesbot.com/docs/#api-comparison
Comment #10
dpiThis looks like a wontfix to me.
I doubt behavior changed as a result of PHP version. And if it did, it would be because of property comparison, for which I think it would be plain luck if it worked before.
\DateTimehas innate comparison magic since PHP 5.2.2. At this time classes cannot implement their own magic comparison [methods].When comparing same userland classes, PHP will check properties, but this does not work with instances of different classes. So you're out of luck if you wanted to compare DTT/DTP/DT.
Comment #11
catchMoving this to a task, we could possibly add a helper to ease comparison per neclimdul's suggestion in #9, but this isn't a critical bug.
Comment #14
moshe weitzman commentedI have to say that this is surprising that our wrapper class is less functional than the built-in DateTime class. Helper methods would be much appreciated.
Comment #16
rob230 commentedSo can we really not use comparison operators with DrupalDateTime? That's quite a setback. There should be a compare method at least. Instead I suppose we have to format it and compare the strings?
Comment #21
quietone commented@clayfreeman, thanks for pointing this problem out and providing a patch.
This issue is about a problem with PHP 7.3, which is EOL and is not used by a currently supported version of Drupal. Therefore I am closing this issue.
Comment #22
jonathanshaw@quietone I don't see any discussion in this issue about whether this is or is not a problem with php 7.4+ or php 8. Maybe it was first reported when php 7.3 was the current version of php. The test coverage provided in the patch would seem useful even if it was not a current problem.
Comment #23
alexpottThe problem is that the same date with different langcodes will not compare correctly. PHP's built \DateTime does compare properly and if it was the only property on our DateTimePlus objects then they would compare correctly too. But it's not so that don't and there is nothing we can do about this. I do think we should add a compare method to make things simpler...
Something like:
One thing that will catch people out is that if the the dates have the same langcode then object comparison will work as a user expects and therefore I'd guess that we see a lot of date comparison in custom and contrib.
Comment #24
andypostThere's PHP RFC https://wiki.php.net/rfc/drop_32bit_support to drop some date-functions
Comment #25
neclimdulI thought the discussion on the mailing list was to not touch the functions and just drop the 32bit support