joergi1988 joergi1988 - 6 months ago 53
PHP Question

PHP Datetime Add to DateTime in While loop 30 times

I need help,
i have a while loop with dates for one month from mysql.
i have calculated the difference between times.
now i must sum that all differences at the end.
i have tried a lot. is there any option to add all that differences without writing each day?

while($row = mysqli_fetch_assoc($sql)){ // <---- while loop makes round 30 times... 1 month long
$usern = $row['title'];
$arbeit = $row['description'];
$start_com = $row['start']; // <--- DATETIME
$end_com = $row['end']; // <----- DATETIME
$shop = $row['category'];

$time_from = strtotime( $start_com );
$time_from = date("H:i", $time_from);
$time_to = strtotime( $end_com );
$time_to = date("H:i", $time_to);

$dteStart = new DateTime($start_com);
$dteEnd = new DateTime($end_com);
$dteDiff = $dteStart->diff($dteEnd);

$e = MyDateInterval::fromDateInterval($dteDiff);
$e->add($dteDiff); // ----- this not works


echo '.$dteDiff->format("%H:%I").';

}
// echo $e->format("%H:%I:%S"); // ------- not working...
// <---- here i need sum of the datetimes diff ---->


$dteDiff must at the end the complete diff all times. Can anyone help me?

Answer

Assuming $e is a DateTime object your formatting is not correct for your dates. Please see http://php.net/manual/en/function.date.php

I (capital i) is daylight saving time you should use i for minutes.

S (capital s) is English ordinal suffix for the day of the month, 2 characters such as 2nd, 1st, 5th you should use s for seconds.

So you would need to use $e->format('H:i:s') to display the formatted hours, minutes, and seconds. to output 14:30:54.

As for your functionality, PHP doesn't have a way to add intervals by default, so it's up to you to decide the functionality for your specific needs.

$diffs = array();
while($row = mysqli_fetch_assoc($sql)) {
    $start_com = $row['start']; // <--- DATETIME - PAST
    $end_com = $row['end']; // <----- DATETIME - FUTURE
    $startDate = DateTime::createFromFormat('Y-m-d H:i:s', $start_com);
    $endDate = DateTime::createFromFormat('Y-m-d H:i:s', $end_com);
    if ($startDate && $endDate) {
        $diffs[] = $startDate->diff($endDate);
    }
}

This will allow you to add up the resulting diffs to retrieve the sum of all the diffs. It is important to note that DateInterval is NOT designed to to automatically add roll-over values, meaning 24 hours does not add 1 day.

This step could also be moved into your initial while by checking if a previous diff already exists and adding the resulting current diff.

$dateInterval = null;
foreach($diffs as $diff) {
    if(null === $dateInterval) {
        $dateInterval = $diff;
        continue;
    }
    $dateInterval->y += $diff->y;
    $dateInterval->m += $diff->m;
    $dateInterval->d += $diff->d;
    $dateInterval->h += $diff->h;
    $dateInterval->i += $diff->i;
    $dateInterval->s += $diff->s;
    $dateInterval->days += $diff->days;
}
var_dump($dateInterval);

Outputs:

object(DateInterval)#3 (15) {
  ["days"]=>
  int(779)
  ["y"]=>
  int(367)
  ["m"]=>
  int(164)
  ["d"]=>
  int(430)
  ["h"]=>
  int(313)
  ["i"]=>
  int(871)
  ["s"]=>
  int(979)
   //...
}

You would then need to format the date interval to the desired format, for example hours.

$hours = floor($dateInterval->y * 8760) + 
floor($dateInterval->m * 730.001) +
floor($dateInterval->d * 24) +
$dateInterval->h +
floor($dateInterval->i / 60) +
floor($dateInterval->s / 3600);

echo  'Hours Total: ' . $hours; //Hours Total: 3345287

Example: http://ideone.com/x6xDoe


Simplified

This can be simplified by setting an initial date and a compare date to get the resulting difference from.

$initialDate = new DateTime;
$compareDate = clone $initialDate;
while($row = mysqli_fetch_assoc($sql)) {
    $start_com = $row['start']; // <--- DATETIME - PAST
    $end_com = $row['end']; // <----- DATETIME - FUTURE
    $startDate = DateTime::createFromFormat('Y-m-d H:i:s', $start_com);
    $endDate = DateTime::createFromFormat('Y-m-d H:i:s', $end_com);
    if ($startDate && $endDate) {
        $initialDate->add($startDate->diff($endDate));
    }
}
$sumDiff = $compareDate->diff($initialDate);
var_dump($sumDiff);

Outputs:

object(DateInterval)#6 (15) {
  ["y"]=>
  int(312)
  ["m"]=>
  int(3)
  ["d"]=>
  int(12)
  ["h"]=>
  int(19)
  ["i"]=>
  int(53)
  ["s"]=>
  int(50)
  //...
}

Example: http://ideone.com/v9bzLe

Comments