Каков наилучший (независимый от формата даты способ) в PHP для расчета разницы в днях между двумя датами в указанном формате.
Я попробовал следующую функцию:
function get_date_offset($start_date, $end_date)
{
$start_time = strtotime($start_date);
$end_time = strtotime($end_date);
return round(($end_time-$start_time)/(3600*24));
}
Он работает нормально в Linux, но при запуске под Windows возвращается strtotime ''.
РЕДАКТИРОВАТЬ:
Дата ввода находится в формате мм / дд / гггг, но я хотел бы, чтобы он принимал формат $ в качестве параметра.
Мне нужна только разница в днях.
Кстати - это не лучший способ. Рассмотрим, например, вычитание 23:00 22.12.2008 из 01:00 23.12.2008. У вас будет 2 часа. Ваш алгоритм скажет - 0 дней. Но это будет на следующий день!






Я не уверен, что считается Лучший, поскольку в PHP нет встроенной функции для этого, но некоторые люди использовали грегориантойд (), например, в это сообщение на форуме.
Проблема с PHP в том, что у него нет определенного типа DateTime. Вы можете использовать временную метку Unix или встроенный класс DateTime, но их функциональность довольно ограничена. Я ожидаю, что должны быть некоторые сторонние классы с более широкой поддержкой вычислений даты и времени, но я не искал этого.
Использование временных меток Unix для вычисления даты (не времени) также сложно. Вам придется отказаться от временной части, но простой сброс на 00:00 небезопасен из-за перехода на летнее время (DST). Летнее время приводит к тому, что в году есть два дня, а не ровно 24 часа. Таким образом, при сложении / вычитании дат вы можете получить значение, которое не делится равномерно на 3600 * 24.
Я бы посоветовал поискать какой-нибудь сторонний класс, который имеет надлежащую поддержку для всего этого. Вычисления даты и времени просто ужасны в своем безобразии. :П
Класс PEAR Date предлагает всевозможные функции для поиска различий между датами, а также около 1000 других вещей. Документы для него: здесь...
В Zend Framework есть класс Zend_Date для работы с «математикой дат». Он работает с ограничениями временных меток, специфичных для системы, с помощью расширения BCMath, или, если он недоступен, ограничивает временные метки максимальным значением с плавающей запятой для вашей системы.
// example printing difference in days
require('Zend/Date.php');
$date1 = new Zend_Date();
$date1->set(2, Zend_Date::MONTH);
$date1->set(27, Zend_Date::DAY);
$date1->set(2008, Zend_Date::YEAR);
$date2 = new Zend_Date();
$date2->set(3, Zend_Date::MONTH);
$date2->set(3, Zend_Date::DAY);
$date2->set(2008, Zend_Date::YEAR);
echo ($date2->getTimestamp() - $date1->getTimestamp()) / (3600*24);
Да, определенно лучший ответ на данный момент.
Если вы не хотите или не можете использовать пакет Zend Framework или Pear, попробуйте эту функцию, надеюсь, это поможет:
function dateDifference($date1, $date2)
{
$d1 = (is_string($date1) ? strtotime($date1) : $date1);
$d2 = (is_string($date2) ? strtotime($date2) : $date2);
$diff_secs = abs($d1 - $d2);
$base_year = min(date("Y", $d1), date("Y", $d2));
$diff = mktime(0, 0, $diff_secs, 1, 1, $base_year);
return array
(
"years" => abs(substr(date('Ymd', $d1) - date('Ymd', $d2), 0, -4)),
"months_total" => (date("Y", $diff) - $base_year) * 12 + date("n", $diff) - 1,
"months" => date("n", $diff) - 1,
"days_total" => floor($diff_secs / (3600 * 24)),
"days" => date("j", $diff) - 1,
"hours_total" => floor($diff_secs / 3600),
"hours" => date("G", $diff),
"minutes_total" => floor($diff_secs / 60),
"minutes" => (int) date("i", $diff),
"seconds_total" => $diff_secs,
"seconds" => (int) date("s", $diff)
);
}
Не будем перегибать палку, ребята.
$d1 = strtotime($first_date);
$d2 = strtotime($second_date);
$delta = $d2 - $d1;
$num_days = ($delta / 86400);
Это то же самое, что и в вопросе. Проблема в том, что strtotime не работает в окне Windows так же, как в Linux, и что он не может анализировать произвольные форматы даты.
gregoriantojd () дает те же результаты, что и использование strtotime (), см. этот блог, чтобы узнать, как это сделать:
Следующее работает для меня. Поверьте, я нашел его где-то в документации php.net.
* Edit - Woops, не видел сообщение csl. Это точная функция из его ссылки, должно быть, я ее нашел. ;)
//Find the difference between two dates
function dateDiff($startDate, $endDate)
{
// Parse dates for conversion
$startArry = date_parse($startDate);
$endArry = date_parse($endDate);
// Convert dates to Julian Days
$start_date = gregoriantojd($startArry["month"], $startArry["day"], $startArry["year"]);
$end_date = gregoriantojd($endArry["month"], $endArry["day"], $endArry["year"]);
// Return difference
return round(($end_date - $start_date), 0);
}
Я пытался вычислить разницу двух дат, чтобы показать продолжительность события. Большинство функций, указанных в задаче, не работают, если событие длится с пятницы с 17:00 до воскресенья в 15:00. Моей целью было найти разницу между такими датами, как:
date('Ymd',$end)-date('Tmd',$begining);
Но это, скорее всего, потерпит неудачу, потому что в году нет 99 месяцев и 99 дней в месяце. Я мог бы преобразовать строку даты в временную метку UNIX и разделить ее на 60 * 60 * 12, но в некоторые дни количество часов больше или меньше, а иногда бывает и так. Поэтому я создал свою собственную функцию, используя getdate (), функцию, которая возвращает массив информации о метке времени.
/*
* datediff($first,$last)
* $first - unix timestamp or string aksepted by strtotime()
* $last - unix timestamp or string aksepted by strtotime()
*
* return - the difference in days betveen the two dates
*/
function datediff($first,$last){
$first = is_numeric($first) ? $first : strtotime($first);
$last = is_numeric($last ) ? $last : strtotime($last );
if ($last<$first){
// Can't calculate negative difference in dates
return -1;
}
$first = getdate($first);
$last = getdate($last );
// find the difference in days since the start of the year
$datediff = $last['yday'] - $first['yday'];
// if the years do not match add the appropriate number of days.
$yearCountedFrom = $first['year'];
while($last['year'] != $yearCountedFrom ){
// Take leap years into account
if ( $yearCountedFrom % 4 == 0 && $yearCountedFrom != 1900 && $yearCountedFrom != 2100 ){
//leap year
$datediff += 366;
}else{
$datediff += 365;
}
$yearCountedFrom++;
}
return $datediff;
}
Что касается функции GregorianToJD (), она может сработать, но мне немного не по себе, так как я не понимаю, как она работает.
Вычислите разницу между двумя датами (и временем) с помощью Php. На следующей странице представлен ряд различных методов (всего 7) для вычисления даты / времени с использованием Php, чтобы определить разницу во времени (часы, муниты), днях, месяцах или годах между двумя датами.
См. Php Date Time - 7 методов расчета разницы между двумя датами
В PHP 5.2 представлены классы DateTime и DateInterval, которые упрощают эту задачу:
function get_date_offset($start_date, $end_date)
{
$start_time = new DateTime($start_date);
$end_time = new DateTime($end_date);
$interval = $end_time->diff($start_time);
return $interval->format('%a days');
}
Как выглядят $ start_date и $ end_date?