PrimuS
PrimuS

Reputation: 2683

PHP check if two Datetimes are not on the same calendar day

I have two Datetimes like this (the dates being actually $vars)

$startTime = \DateTime::createFromFormat('Y/m/d H:i', '2015/01/01 23:00');
$endTime = \DateTime::createFromFormat('Y/m/d H:i', '2015/01/02 01:00');

I struggle with a (possibly pretty) simple problem: How could I determine if the two dates are on different calendar days?

I cannot do < as 2015/01/01 22:00 < 2015/01/01 23:00 would also be true. I can also not do this:

$diff = $startTime->diff($endTime);
$days = $diff->format('%d');

echo $days;

as it gives me 0.

THIS gives me an idea about how to do it, but for javascript, what would be the equivalent for php?

//UPDATE

    $startDate = $startTime->format('Y/m/d');
    $endDate = $endTime->format('Y/m/d');
    $diffDates = $startDate->diff($endDate);
    $daysDiff = $diffDates->format('%d');

    echo $daysDiff;

I think that might be the right approach now, thanks to the comments, but now I get Error: Call to a member function diff() on string

//UPDATE FOR CLARIFICATION WHAT I'M TRYING TO DO

I just want to have the difference in days, so for the above it would be '1' (although only 2 hours difference actually) and for example '2015/01/01 23:00' and '2015/01/03 17:00' would be '2'.

Upvotes: 3

Views: 4427

Answers (3)

KyleK
KyleK

Reputation: 5056

Comparing formatted dates is the right thing to do:

$a->format('Y-m-d') === $b->format('Y-m-d')

There is a method for that if you use Carbon:

$dt1->isSameDay($dt2)

So I recommend to use it instead of previous answers given here.

http://carbondoc/docs/#api-comparison

Upvotes: 2

&#193;lvaro Gonz&#225;lez
&#193;lvaro Gonz&#225;lez

Reputation: 146390

I think this is one of the few situations where the use of strings for date calculations is justified:

function onDifferentDays(\DateTimeInterface $startTime, \DateTimeInterface $endTime){
    return $startTime->format('Y-m-d')!==$endTime->format('Y-m-d');
}

This code should be easy to extend to include time zone.

There're other alternatives but I don't think they're normally worth the effort:

  1. Compare element by element (day, month and year):

    • The PHP DateTime class doesn't offer dedicated functions, only format().
  2. Normalize both dates to a common time and compare with == (not ===):

    • Unless you're using immutable objects you need to clone input or expect side effects

    • You also need to ensure that time exists in the active time zone though midnight is probably safe enough.

Whatever, YMMV ;-)

Upvotes: 3

Furgas
Furgas

Reputation: 2844

Just create the dates with time set to 00:00:00:

$startTime = \DateTime::createFromFormat('Y/m/d H:i:s', '2015/01/01 00:00:00');
$endTime = \DateTime::createFromFormat('Y/m/d H:i:s', '2015/01/02 00:00:00');

or reset time to zero on existing dates:

$startTime->setTime(0, 0, 0);
$endTime->setTime(0, 0, 0);

then it should work:

$diff = $startTime->diff($endTime);
$days = $diff->format('%d');

echo $days; // 1

Bonus

If you want to work only with dates, remember to set the time to 00:00:00 in createFromFormat or reset it with setTime. If you won't provide time in createFromFormat PHP will set it to the current time:

$date = DateTime::createFromFormat('Y-m-d', '2016-01-21');
print $date->format('H:i:s'); //not 00:00:00

To fix it, you must either:

  • provide 00:00:00 time in format:

    $date = DateTime::createFromFormat('Y-m-d H:i:s', '2016-01-21 00:00:00');

  • prefix the date format with exclamation mark and omit the time, this will set the time to 00:00:00 automatically:

    $date = DateTime::createFromFormat('!Y-m-d', '2016-01-21');

  • reset the time after creation:

    $date = DateTime::createFromFormat('Y-m-d', '2016-01-21'); $date->setTime(0, 0);

Upvotes: 3

Related Questions