Рассчитать количество часов между двумя датами в PHP

Как рассчитать разницу между двумя датами в часах?

Например:

day1=2006-04-12 12:30:00 day2=2006-04-14 11:30:00 

В этом случае результат должен составлять 47 часов.

Новые версии PHP-версии предоставляют несколько новых классов, называемых DateTime , DateInterval , DateTimeZone и DatePeriod . Классная вещь в этом классе заключается в том, что он рассматривает разные временные интервалы, високосные годы, прыжки секунд, летнее время и т. Д. И вдобавок к этому он очень прост в использовании. Вот что вы хотите с помощью этих объектов:

 // Create two new DateTime-objects... $date1 = new DateTime('2006-04-12T12:30:00'); $date2 = new DateTime('2006-04-14T11:30:00'); // The diff-methods returns a new DateInterval-object... $diff = $date2->diff($date1); // Call the format method on the DateInterval-object echo $diff->format('%a Day and %h hours'); 

Возвращаемый объект DateInterval также предоставляет другие методы, кроме format . Если вы хотите получить результат только в часах, вы можете сделать что-то вроде этого:

 $date1 = new DateTime('2006-04-12T12:30:00'); $date2 = new DateTime('2006-04-14T11:30:00'); $diff = $date2->diff($date1); $hours = $diff->h; $hours = $hours + ($diff->days*24); echo $hours; 

И вот ссылки для документации:

  • DateTime-класс
  • DateTimeZone-класс
  • DateInterval-класс
  • DatePeriod-класс

Все эти классы также предлагают процедурный / функциональный способ работы с датами. Поэтому взгляните на обзор: http://php.net/manual/book.datetime.php

 $t1 = StrToTime ( '2006-04-14 11:30:00' ); $t2 = StrToTime ( '2006-04-12 12:30:00' ); $diff = $t1 - $t2; $hours = $diff / ( 60 * 60 ); 

ваш ответ:

round((strtotime($day2) - strtotime($day1))/(60*60))

Самый простой способ получить правильное количество часов между двумя датами (datetimes), даже при изменении летнего времени, – использовать разницу в отметках времени Unix. Временные метки Unix – это секунды, прошедшие с 1970-01-01T00: 00: 00 UTC, игнорируя секунды прыжка (это нормально, потому что вам, вероятно, не нужна эта точность, и из-за того, что во время прыжка довольно сложно).

Самый гибкий способ конвертировать строку datetime с дополнительной информацией о часовом поясе в временную метку Unix – это построить объект DateTime (необязательно с DateTimeZone в качестве второго аргумента в конструкторе), а затем вызвать его метод getTimestamp .

 $str1 = '2006-04-12 12:30:00'; $str2 = '2006-04-14 11:30:00'; $tz1 = new DateTimeZone('Pacific/Apia'); $tz2 = $tz1; $d1 = new DateTime($str1, $tz1); // tz is optional, $d2 = new DateTime($str2, $tz2); // and ignored if str contains tz offset $delta_h = ($d2->getTimestamp() - $d1->getTimestamp()) / 3600; if ($rounded_result) { $delta_h = round ($delta_h); } else if ($truncated_result) { $delta_h = intval($delta_h); } echo "Δh: $delta_h\n"; 

Предоставить другой метод DatePeriod .

Он учитывает переход на летнее время в применимые часовые пояса, без необходимости делать математику по количеству секунд или часов между датами.

Количество часов (например: https://3v4l.org/Vom6N )

 $date1 = new \DateTime('2006-04-12T12:30:00'); $date2 = new \DateTime('2006-04-14T11:30:00'); //determine what interval should be used - can change to weeks, months, etc $interval = new \DateInterval('PT1H'); //create periods every hour between the two dates $periods = new \DatePeriod($date1, $interval, $date2); //count the number of objects within the periods $hours = iterator_count($periods); echo $hours . ' hours'; 

результат

 47 hours 

Подсчет часов с летней экономией (например: https://3v4l.org/eO9KE )

 //set timezone to UTC to disregard daylight savings ini_set('date.timezone', 'America/New_York'); $date1 = new \DateTime('2006-01-01T12:00:00'); $date2 = new \DateTime('2006-06-01T12:00:00'); $interval = new \DateInterval('PT1H'); $periods = new \DatePeriod($date1, $interval, $date2); $hours = iterator_count($periods); echo $hours . ' hours'; 

результат

 3623 hours 

Тот же метод может использоваться для определения периодов оплаты и поиска дат вместо их подсчета.

Период оплаты (например: https://3v4l.org/WQoh5 )

 $interval = new \DateInterval('P2W'); $payPeriodStart = new \DateTime('2012-08-12T00:00:00'); $today = new \DateTime('2016-03-04T12:00:00'); $today->add($interval); $payPeriods = new \DatePeriod($payPeriodStart, $interval, $today); $payPeriods = array_reverse(iterator_to_array($payPeriods)); $recent = [ 'current' => [ 'start' => $payPeriods[1]->format('Ym-d'), 'end' => $payPeriods[0]->format('Ym-d') ], 'previous' => [ 'start' => $payPeriods[2]->format('Ym-d'), 'end' => $payPeriods[1]->format('Ym-d') ] ]; var_dump($recent); 

результат

 array(2) { ["current"]=> array(2) { ["start"]=> string(10) "2016-02-21" ["end"]=> string(10) "2016-03-06" } ["previous"]=> array(2) { ["start"]=> string(10) "2016-02-07" ["end"]=> string(10) "2016-02-21" } } 
 //Calculate number of hours between pass and now $dayinpass = "2013-06-23 05:09:12"; $today = time(); $dayinpass= strtotime($dayinpass); echo round(abs($today-$dayinpass)/60/60); 
 $day1 = "2006-04-12 12:30:00" $day1 = strtotime($day1); $day2 = "2006-04-14 11:30:00" $day2 = strtotime($day2); $diffHours = round(($day2 - $day1) / 3600); 

Я предполагаю, что функция strtotime () принимает этот формат даты.

К сожалению, решение, предоставленное FaileN, не работает, как заявил Уолтер Тросс .. дни могут быть не 24 часа!

Мне нравится использовать PHP-объекты, где это возможно, и для большей гибкости я придумал следующую функцию:

 /** * @param DateTimeInterface $a * @param DateTimeInterface $b * @param bool $absolute Should the interval be forced to be positive? * @param string $cap The greatest time unit to allow * * @return DateInterval The difference as a time only interval */ function time_diff(DateTimeInterface $a, DateTimeInterface $b, $absolute=false, $cap='H'){ // Get unix timestamps, note getTimeStamp() is limited $b_raw = intval($b->format("U")); $a_raw = intval($a->format("U")); // Initial Interval properties $h = 0; $m = 0; $invert = 0; // Is interval negative? if(!$absolute && $b_raw<$a_raw){ $invert = 1; } // Working diff, reduced as larger time units are calculated $working = abs($b_raw-$a_raw); // If capped at hours, calc and remove hours, cap at minutes if($cap == 'H') { $h = intval($working/3600); $working -= $h * 3600; $cap = 'M'; } // If capped at minutes, calc and remove minutes if($cap == 'M') { $m = intval($working/60); $working -= $m * 60; } // Seconds remain $s = $working; // Build interval and invert if necessary $interval = new DateInterval('PT'.$h.'H'.$m.'M'.$s.'S'); $interval->invert=$invert; return $interval; } 

Это подобно date_diff() создает DateTimeInterval , но с наивысшей единицей как часы, а не годами .. он может быть отформатирован как обычно.

 $interval = time_diff($date_a, $date_b); echo $interval->format('%r%H'); // For hours (with sign) 

NB Я использовал format('U') вместо getTimestamp() из-за комментария в руководстве . Также обратите внимание, что 64-бит требуется для дат после эпохи и до отрицательных эпох!

 <? $day1 = "2014-01-26 11:30:00"; $day1 = strtotime($day1); $day2 = "2014-01-26 12:30:00"; $day2 = strtotime($day2); $diffHours = round(($day2 - $day1) / 3600); echo $diffHours; ?> 

Эта функция поможет вам рассчитать точные годы и месяцы между двумя заданными датами, $doj1 и $doj . Он возвращает пример 4.3 означает 4 года и 3 месяца.

 <?php function cal_exp($doj1) { $doj1=strtotime($doj1); $doj=date("m/d/Y",$doj1); //till date or any given date $now=date("m/d/Y"); //$b=strtotime($b1); //echo $c=$b1-$a2; //echo date("Ymd H:i:s",$c); $year=date("Y"); //$chk_leap=is_leapyear($year); //$year_diff=365.25; $x=explode("/",$doj); $y1=explode("/",$now); $yy=$x[2]; $mm=$x[0]; $dd=$x[1]; $yy1=$y1[2]; $mm1=$y1[0]; $dd1=$y1[1]; $mn=0; $mn1=0; $ye=0; if($mm1>$mm) { $mn=$mm1-$mm; if($dd1<$dd) { $mn=$mn-1; } $ye=$yy1-$yy; } else if($mm1<$mm) { $mn=12-$mm; //$mn=$mn; if($mm!=1) { $mn1=$mm1-1; } $mn+=$mn1; if($dd1>$dd) { $mn+=1; } $yy=$yy+1; $ye=$yy1-$yy; } else { $ye=$yy1-$yy; $ye=$ye-1; $mn=12-1; if($dd1>$dd) { $ye+=1; $mn=0; } } $to=$ye." year and ".$mn." months"; return $ye.".".$mn; /*return daysDiff($x[2],$x[0],$x[1]); $days=dateDiff("/",$now,$doj)/$year_diff; $days_exp=explode(".",$days); return $years_exp=$days; //number of years exp*/ } ?> в <?php function cal_exp($doj1) { $doj1=strtotime($doj1); $doj=date("m/d/Y",$doj1); //till date or any given date $now=date("m/d/Y"); //$b=strtotime($b1); //echo $c=$b1-$a2; //echo date("Ymd H:i:s",$c); $year=date("Y"); //$chk_leap=is_leapyear($year); //$year_diff=365.25; $x=explode("/",$doj); $y1=explode("/",$now); $yy=$x[2]; $mm=$x[0]; $dd=$x[1]; $yy1=$y1[2]; $mm1=$y1[0]; $dd1=$y1[1]; $mn=0; $mn1=0; $ye=0; if($mm1>$mm) { $mn=$mm1-$mm; if($dd1<$dd) { $mn=$mn-1; } $ye=$yy1-$yy; } else if($mm1<$mm) { $mn=12-$mm; //$mn=$mn; if($mm!=1) { $mn1=$mm1-1; } $mn+=$mn1; if($dd1>$dd) { $mn+=1; } $yy=$yy+1; $ye=$yy1-$yy; } else { $ye=$yy1-$yy; $ye=$ye-1; $mn=12-1; if($dd1>$dd) { $ye+=1; $mn=0; } } $to=$ye." year and ".$mn." months"; return $ye.".".$mn; /*return daysDiff($x[2],$x[0],$x[1]); $days=dateDiff("/",$now,$doj)/$year_diff; $days_exp=explode(".",$days); return $years_exp=$days; //number of years exp*/ } ?> в <?php function cal_exp($doj1) { $doj1=strtotime($doj1); $doj=date("m/d/Y",$doj1); //till date or any given date $now=date("m/d/Y"); //$b=strtotime($b1); //echo $c=$b1-$a2; //echo date("Ymd H:i:s",$c); $year=date("Y"); //$chk_leap=is_leapyear($year); //$year_diff=365.25; $x=explode("/",$doj); $y1=explode("/",$now); $yy=$x[2]; $mm=$x[0]; $dd=$x[1]; $yy1=$y1[2]; $mm1=$y1[0]; $dd1=$y1[1]; $mn=0; $mn1=0; $ye=0; if($mm1>$mm) { $mn=$mm1-$mm; if($dd1<$dd) { $mn=$mn-1; } $ye=$yy1-$yy; } else if($mm1<$mm) { $mn=12-$mm; //$mn=$mn; if($mm!=1) { $mn1=$mm1-1; } $mn+=$mn1; if($dd1>$dd) { $mn+=1; } $yy=$yy+1; $ye=$yy1-$yy; } else { $ye=$yy1-$yy; $ye=$ye-1; $mn=12-1; if($dd1>$dd) { $ye+=1; $mn=0; } } $to=$ye." year and ".$mn." months"; return $ye.".".$mn; /*return daysDiff($x[2],$x[0],$x[1]); $days=dateDiff("/",$now,$doj)/$year_diff; $days_exp=explode(".",$days); return $years_exp=$days; //number of years exp*/ } ?> 

Это работает в моем проекте. Я думаю, это будет полезно для вас.

Если Date находится в прошлом, инвертирование будет 1.
Если Date в будущем, то инвертирование будет 0.

 $defaultDate = date('Ym-d'); $datetime1 = new DateTime('2013-03-10'); $datetime2 = new DateTime($defaultDate); $interval = $datetime1->diff($datetime2); $days = $interval->format('%a'); $invert = $interval->invert; 

Чтобы передать временную метку unix, используйте эту нотацию

 $now = time(); $now = new DateTime("@$now");