There are two timestamps stored in two variables: $startTimestamp = "2023-08-05 14:45:05"
and $endTimestamp = "2023-08-09 12:00:14"
.
I am only able to get the total difference between the timestamps but not individual intervals. I need to get the time consumed on each day between the two timestamps. How to proceed?
What I have tried?
$startTimestamp = "2023-08-05 14:45:05";
$endTimestamp = "2023-08-09 13:00:14";
$begin = new DateTime($startTimestamp);
$end = new DateTime($endTimestamp);
$startDate = date("Y-m-d", strtotime($startTimestamp));
$endDate = date("Y-m-d", strtotime($endTimestamp));
if($startDate == $endDate)
{
$return = [
"$startDate" => round(abs(strtotime($endTimestamp) - strtotime($startTimestamp)) / 60,2)
];
}
else
{
$return = [];
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($begin, $interval, $end);
foreach ($period as $dt)
{
$date_this = $dt->format("Y-m-d");
if($date_this == $startDate)
{
$startEnd = $date_this." 23:59:59";
$return[] = ["$date_this" => round(abs(strtotime($startEnd) - strtotime($startTimestamp)) / 60,2)];
}
elseif ($date_this == $endDate)
{
$endStart = $date_this." 00:00:00";
$return[] = ["$date_this" => round(abs(strtotime($endTimestamp) - strtotime($endStart)) / 60,2)];
}
else
{
$return[] = ["$date_this" => 1440];
}
}
}
Expected output:
2023-08-05: 555 minutes
2023-08-06: 1440 minutes
2023-08-07: 1440 minutes
2023-08-08: 1440 minutes
2023-08-09: 885 minutes
Problem – Actual output:
2023-08-05: 554.9 minutes
2023-08-06: 1440 minutes
2023-08-07: 1440 minutes
2023-08-08: 1440 minutes
The 5th date is missing when end timestamp’s hour is less than start timestamp’s hour.
2
Answers
Do not mix
DateTime
with the old date & time functions (date()
,time()
,strtotime()
, etc). The old function provide poor support for timezones (or no support at all) and working with them is cumbersome. The newDateTime
classes are easier to work with and can express better the business logic, hiding the technical details.The algorithm below splits the input interval into calendar days then, for each day, compute the fragment of the day that is included in the input interval. It then expresses each of these fragments in minutes.
The algorithm does not handle the days when the DST changes (if DST applies to your timezone) but rest assured, the
DateTime
classes handle them correctly.It also does not handle the special case when the start and end timestamps lay on the same calendar day. If this case needs a special handling then it can be done after the
foreach
loop, on the output array (it has only one item when this special case happens).Check it online.
axiac already copied my code to write an answer, but I still think my code can be useful in an answer.
As I said in my comment: Your mixing different ways of representing dates and time, which is confusing. I’ve created a solution that only uses one way:
which returns:
See: https://3v4l.org/5Af18#v8.2.10
I extracted the code to compute the difference, in minutes, between two datetimes, because that can be a useful function. I also turned the algorithm itself into a function so there are no global variables that can interfere with other code.