I have the following code working in Laravel 8 (which uses Carbon by default) with PHP7.
$carbon = new Carbon();
$test1 = 1;
$test2 = 1;
if ($carbon > '1970-01-01 00:00:00') {
$test1 = 2;
}
if ($carbon > '2030-01-01 00:00:00') {
$test2 = 2;
}
# ends with $test1===2 and $test2===1
The problem is that when I searched this usage I found many posts indicating they had to something much more complicated.
However all those posts are about 3-4 years old. Is this a newly supported feature of Carbon or my working code was just pure luck and there are cases not working?
EDIT:
I found in the greaterThan
function implementation that even they are using raw string in the example for their compare-target date. This seems so weird considering all the content of other online posts.
/**
* Determines if the instance is greater (after) than another
*
* @example
* ```
* Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:15'); // true
* Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:16'); // false
* Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:17'); // false
* ```
*
* @param \Carbon\Carbon|\DateTimeInterface|mixed $date
*
* @return bool
*/
public function greaterThan($date): bool
{
return $this > $date;
}
CodePudding user response:
It's not new, and it's not even a Carbon
feature, any class having a __toString
method can be compared to an other string.
And when you compare strings with <
, <=
, >
or >=
, PHP just sorts them alphabetically (alphabet here is actually the order of the characters in the ASCII table).
So here is what actually happens:
class Foo
{
public function __construct($input)
{
$this->input = $input;
}
public function __toString()
{
return $this->input;
}
}
var_dump(new Foo('A') < 'B'); // true
var_dump(new Foo('0') < '1'); // true
var_dump(new Foo('C') < 'B'); // false
var_dump(new Foo('a') < 'B'); // false, lower case = higher ASCII rank
var_dump(new Foo('2-0') < '1-9'); // false
As you see with last example, digits in strings also are characters in the ASCII table and there order in the table matches the numerical order (0 to 9).
And by default when you convert a Carbon
object to string (explicitly or implicitly like here) it returns an ISO-8601 string.
This format is handy as until year 9999, dates will all have the same length and the same number of digits for each component, so sorting strings will match the intent of sorting dates.
If you are 100% you won't customize the __toString
method of the Carbon
object and 100% sure you always compare to a ISO-8601 string, comparing date with string like you do is fine, and I would even say, it's the cleanest way.
But as you see it implies some prerequisites.
Last thing: you can also compare 2 Carbon
object:
var_dump(new Carbon('2030-01-01 00:00:00') > new Carbon('1970-01-01 00:00:00')); // true
This actually relies on a other feature: PHP provides native comparison of DateTime
objects and Carbon
extends DateTime
When the prerequisites above are not certain or if you want to be more explicit, I recommend you actually parse the string and compare objects to rely on this native PHP DateTime
comparison.
Note that what you found in the doc of greaterThan
recommend comparing Carbon
<> Carbon
, not Carbon
<> string
Because: comparing different types is always at the risk that you/the next developer don't fully control/understand the implicit cast happening.