PHP calculating remaining time between two dates

I managed to make it count difference of two dates, but because it actually counts time difference once you get past target date it starts counting up (and I need remaining days then show overdue days with negative indicator “-” plus a note ). I have sorted the note but it only works if remaining months and days equals 0.

Code:

<?php 
$v = $row_rsHardwareAsset['maintenanceint'];
$date = $row_rsHardwareAsset['lastmaint'];
$date = strtotime(date("Y-m-d", strtotime($date)) . " +$v month");
$date = date("Y-m-d", $date); // next maintenance day


$date1 = date("Y-m-d");
$date2 = $date;

$diff = abs(strtotime($date2) - strtotime($date1));

$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));

if ($months == 0 && $days == 0) { 
	echo "<h1>MAINTENANCE OVERDUE!</h1>"; 
	} else printf("%d months, %d days\n", $months, $days);
?>

Could you not use something like DateTime objects and diff() to simplify things?

http://php.net/manual/en/datetime.diff.php

But surely that’s because your code asks exactly that:

if ($months == 0 && $days == 0) { 

You need to widen that check to encompass whatever values make it overdue.

Read up on that link though, because on first glance without any testing it seems that your code above is based on all months having 30 days.

Not to mention that DateTime objects in PHP support direct comparison (date1 < date2)…

I do, but I don’t know how, so hence I am asking help here :slight_smile:

And it’s absolutely fine to base month on 30 days, this is not critical.

Well there’s no NEED to base it off 30 days, if you can be more accurate with actually LESS work.

How to construct DateTimes (read the examples, not the technical jargon at the top)
Then read the bit about DateTime Diff
Then look at the definition of a DateInterval Object (which is what DateTime::diff returns)

Note that if the only thing you care about is “is this date in the past or the future”, you dont actually need to do a diff, just say if($thetargetdate < $todaysdate).

I have seen many samples on web with diff function but none of them worked for me and the code I have posted is the only one that works? I know diff is very simple and quick way to do this job but I have struggled…

So, assuming that this code you have posted above is all you’re doing with the dates, this code can be 8 lines long.
1: Create a DateTime from your date values.
2: Create a DateTime for Now. (Hint: The parameter of the constructor is optional.)
3: Calculate the Diff of those two objects.
4: if (line1 < line2)
5: post message
6: } else {
7: post message
8: }

Give it a try.

There is no need for a cluster muck of code gymnastics to get a date difference. The DB is more than capable of doing it with SQL. At its most basic this is all you need.

SELECT DATEDIFF(“2017-06-25”, “2017-06-15”);

SELECT DATEDIFF(date_column1, date_column2);

That may be true for mysql (it’s actually not true for all databases). It still needs ‘gymnastics’ because it still needs to add another (integer) field as months to the date stored, and it still needs to do NOW(), so… it still does all the same ‘gymnastics’, but does it at the database end.

With an added bonus of latency. Doing these things in PHP is much faster than letting the database do it.

1 Like

Citation or Benchmark proof please.

2 Likes

Personally I find it difficult to gauge the difference between the two on so small a scale as these operations; the variance in my testing was so significant that the answer I came up with was “it depends on what my CPU feels like at the time.” Course i was running all my tests locally; across a network, on a database server that may be busier than hosting a single table on a single database… shrug

In general, my SQL-calculated tests slowed down more than PHP with the more rows that I pulled. So perhaps it’s a different variable that needs to be examined.

In any case, the code complexity doesnt change much between the two, and flexibility for additional uses and use cases favors PHP.

Well, PHP is purely in memory whereas MySQL has at least network overhead. This might be low if you’re on a local machine as @m_hutley says, but once that database server is physically separated from the server running PHP you will certainly feel that latency.

See http://www.prowesscorp.com/computer-latency-at-a-human-scale/ - PHP will not surpass “Memory” level, whereas MySQL will.

EDIT: Of course if you’re already querying the database anyway it might be easier to include that in the query as well, I was more thinking about a case where you’re just querying the database just calculate the difference between two supplied dates, that wouldn’t make sense.

Do not forget the calculation includes two dates - “lastmaint date” & “next maint date” so you get result of how many days left to text maintenance. Another point to make - “servicing interval” is set by number i.e. 3 (which indicates 3 months) and I need to calculate “next maint date” by adding 3 months to “last maint”.

How do you define three months? eg. first tuesday to first tuesday, the seventh to the seventh, or approximated to 90 days, etc.

Have you looked at the code in the first post?

[‘maintenanceint’] can be - 1; 3; 6; 12 whichever selected when adding asset.

Then this number is turned into $v and calculations follows.

DateTime example, tested on php 5.5.12:

error_reporting(-1);
date_default_timezone_set('Europe/Helsinki');

$someDate = '2018-01-01';
$now = new DateTime();
$someDateDatetime = new DateTime($someDate);

if ($someDateDatetime < $now) {
    echo 'someDate is in the past.</br>';
} else {
    echo 'someDate is in the future, or the exact same moment.</br>';
}

$diff = $someDateDatetime->diff($now);

echo 'Differenct between someDate and now: </br>';
echo 'Years: ' . $diff->y . '</br>';
echo 'Months: ' . $diff->m . '</br>';
echo 'Days: ' . $diff->d . '</br>';
echo 'Hours: ' . $diff->h . '</br>';
echo 'Minutes: ' . $diff->i . '</br>';
echo 'Seconds: ' . $diff->s . '</br>';
echo 'Total days: ' . $diff->days;

And where in this code maintenance interval time being picked up?

I agree, hitting the database just for a date difference only is not the best approach. But that is not the case here.

1 Like