Поиск количества дней между двумя датами

Как найти количество дней между двумя датами с помощью PHP?

Ответ 1

$now = time(); // or your date as well
$your_date = strtotime("2010-01-31");
$datediff = $now - $your_date;

echo round($datediff / (60 * 60 * 24));

Ответ 2

Если вы используете PHP 5.3 >, это, безусловно, самый точный способ вычисления разницы:

$earlier = new DateTime("2010-07-06");
$later = new DateTime("2010-07-09");

$diff = $later->diff($earlier)->format("%a");

Ответ 3

От PHP версии 5.3 и выше, новые функции даты/времени добавлены, чтобы получить разницу:

$datetime1 = new DateTime("2010-06-20");

$datetime2 = new DateTime("2011-06-22");

$difference = $datetime1->diff($datetime2);

echo 'Difference: '.$difference->y.' years, ' 
                   .$difference->m.' months, ' 
                   .$difference->d.' days';

print_r($difference);

Результат, как показано ниже:

Difference: 1 years, 0 months, 2 days

DateInterval Object
(
    [y] => 1
    [m] => 0
    [d] => 2
    [h] => 0
    [i] => 0
    [s] => 0
    [invert] => 0
    [days] => 367
)

Надеюсь, что это поможет!

Ответ 4

Преобразуйте даты в временные метки unix, затем выложите один из другого. Это даст вам разницу в секундах, которую вы разделите на 86400 (количество секунд в день), чтобы дать вам приблизительное количество дней в этом диапазоне.

Если ваши даты в формате 25.1.2010, 01/25/2010 или 2010-01-25, вы можете использовать функцию strtotime:

$start = strtotime('2010-01-25');
$end = strtotime('2010-02-20');

$days_between = ceil(abs($end - $start) / 86400);

Использование ceil округляет количество дней до следующего полного дня. Используйте floor вместо этого, если вы хотите получить количество полных дней между этими двумя датами.

Если ваши даты уже находятся в формате timestamp в формате unix, вы можете пропустить преобразование и просто сделать часть $days_between. Для более экзотических форматов даты вам, возможно, придется выполнить некоторый выборочный синтаксический анализ, чтобы получить право.

Ответ 5

TL; DR не использует метки времени UNIX. Не используйте time(). Если вы это сделаете, будьте готовы, если его надежность 98.0825% подведет вас. Используйте DateTime (или Carbon).

Правильный ответ - тот, который дал Сакшам Гупта (другие ответы также верны):

$date1 = new DateTime('2010-07-06');
$date2 = new DateTime('2010-07-09');
$days  = $date2->diff($date1)->format('%a');

Или процедурно как однострочник

/**
 * Number of days between two dates.
 *
 * @param date $dt1    First date
 * @param date $dt2    Second date
 * @return int
 */
function daysBetween($dt1, $dt2) {
    return date_diff(
        date_create($dt2),  
        date_create($dt1)
    )->format('%a');
}

С оговоркой: "% a" указывает на абсолютное количество дней. Если вы хотите, чтобы оно представляло собой целое число со знаком, то есть отрицательное, когда вторая дата находится перед первой, тогда вам нужно использовать префикс "% r" (т.е. format('%r%a')).


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


Длинный ответ: почему деление на 24 * 60 * 60 (86400) небезопасно

Большинство ответов, использующих метки времени UNIX (и 86400 для преобразования их в дни), делают два предположения, которые, вместе взятые, могут привести к сценариям с неправильными результатами и незначительным ошибкам, которые могут быть трудно отследить, и возникают даже через дни, недели или месяцы после успешное развертывание. Дело не в том, что решение не работает - оно работает. Сегодня. Но это может перестать работать завтра.

Первая ошибка не в том, что, когда спрашивают: "Сколько дней прошло со вчерашнего дня?", Компьютер может правдиво ответить на ноль, если между настоящим моментом и моментом, указанным "вчера", прошло менее одного целого дня.

Обычно при преобразовании "дня" в метку времени UNIX получается метка времени для полуночи этого конкретного дня.

Таким образом, с полуночи 1 октября по 15 октября прошло пятнадцать дней. Но между 13:00 1 октября и 14:55 15 октября прошло пятнадцать дней минус 5 минут, и большинство решений, использующих floor() или выполняющих неявное целочисленное преобразование , сообщат на один день меньше ожидаемого.

Итак, "сколько дней назад был Ymd H: i: s"? даст неправильный ответ.

Вторая ошибка - приравнивание одного дня к 86400 секундам. Это почти всегда так - это случается достаточно часто, чтобы не замечать того времени, когда этого не происходит. Но расстояние в секундах между двумя последовательными ночами, безусловно, не равно 86400, по крайней мере, два раза в год, когда наступает летнее время. Сравнение двух дат за границей летнего времени даст неправильный ответ.

Таким образом, даже если вы используете "хак" для принудительной установки всех временных отметок даты на фиксированный час, скажем, полночь (это также делается неявно различными языками и средами, когда вы указываете только день-месяц-год, а не час-минута-секунда; То же самое можно сказать о типе DATE в базах данных, таких как MySQL), широко используемой формуле

 (unix_timestamp(DATE2) - unix_timestamp(DATE1)) / 86400

или же

 floor(time() - strtotime($somedate)) / 86400

вернет, скажем, 17, когда DATE1 и DATE2 находятся в одном и том же сегменте DST года; но он может вернуть 17,042, и еще хуже, 16,958. Использование floor() или любого неявного усечения в целое число затем преобразует то, что должно было быть 17, в 16. В других случаях выражения, такие как "$ days> 17", будут возвращать true для 17.042, даже если это будет означать, что прошедший день количество составляет 18.

И все становится еще хуже, так как такой код не переносим между платформами, потому что некоторые из них могут применять дополнительные секунды, а некоторые нет. На этих платформах разница между двумя датами будет не 86400, а 86401, или, возможно, 86399. Поэтому код, который работал в мае и фактически прошел все тесты, прекратит работу в следующем июне, когда 12.99999 дней будут считаться 12 днями вместо 13. Две даты который работал в 2015 году, не будет работать в 2017 году - те же даты, и ни один год не является високосным. Но между 2018-03-01 и 2017-03-01, на тех платформах, которые заботятся, пройдет 366 дней вместо 365, что сделает 2017 год високосным.

Так что если вы действительно хотите использовать метки времени UNIX:

  • используйте функцию round() умом, а не floor().

  • в качестве альтернативы не рассчитывайте разницу между D1-M1-YYY1 и D2-M2-YYY2. Эти даты будут действительно рассматриваться как D1-M1-YYY1 00:00:00 и D2-M2-YYY2 00:00:00. Скорее, конвертируйте между D1-M1-YYY1 22:30:00 и D2-M2-YYY2 04:30:00. Вы всегда получите остаток около двадцати часов. Это может быть двадцать один час или девятнадцать, а может быть, восемнадцать часов пятьдесят девять минут тридцать шесть секунд. Независимо от того. Это большой запас, который останется там и останется позитивным в обозримом будущем. Теперь вы можете обрезать его с floor() в безопасности.

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

  • использовать библиотеку времени (Datetime, Carbon, что угодно); не катай свой собственный

  • написать всесторонние контрольные примеры с использованием действительно неправильных выборов дат - через границы летнего времени, через високосные годы, за високосные секунды и т.д., а также заурядные даты. В идеале (вызовы datetime выполняются быстро!) Генерируют даты за целые четыре года (и один день), последовательно собирая их из строк и гарантируя, что разница между первым и тестируемым днем неуклонно возрастает на единицу. Это будет гарантировать, что, если что-то изменится в низкоуровневых подпрограммах и исправлениях високосных секунд, попытается нанести ущерб, по крайней мере, вы будете знать.

  • регулярно запускайте эти тесты вместе с остальным набором тестов. Они считаются миллисекундами и могут сэкономить вам буквально часы царапин на голове.


Каким бы ни было ваше решение, протестируйте его!

Функция funcdiff ниже реализует одно из решений (как это принято, принятое) в реальном сценарии.

<?php
$tz         = 'Europe/Rome';
$yearFrom   = 1980;
$yearTo     = 2020;
$verbose    = false;

function funcdiff($date2, $date1) {
    $now        = strtotime($date2);
    $your_date  = strtotime($date1);
    $datediff   = $now - $your_date;
    return floor($datediff / (60 * 60 * 24));
}
########################################

date_default_timezone_set($tz);
$failures   = 0;
$tests      = 0;

$dom = array ( 0, 31, 28, 31, 30,
                  31, 30, 31, 31,
                  30, 31, 30, 31 );
(array_sum($dom) === 365) || die("Thirty days hath September...");
$last   = array();
for ($year = $yearFrom; $year < $yearTo; $year++) {
    $dom[2] = 28;
    // Apply leap year rules.
    if ($year % 4 === 0)   { $dom[2] = 29; }
    if ($year % 100 === 0) { $dom[2] = 28; }
    if ($year % 400 === 0) { $dom[2] = 29; }
    for ($month = 1; $month <= 12; $month ++) {
        for ($day = 1; $day <= $dom[$month]; $day++) {
            $date = sprintf("%04d-%02d-%02d", $year, $month, $day);
            if (count($last) === 7) {
                $tests ++;
                $diff = funcdiff($date, $test = array_shift($last));
                if ((double)$diff !== (double)7) {
                    $failures ++;
                    if ($verbose) {
                        print "There seem to be {$diff} days between {$date} and {$test}\n";
                    }
                }
            }
            $last[] = $date;
        }
    }
}

print "This function failed {$failures} of its {$tests} tests between {$yearFrom} and {$yearTo}.\n";

В результате

This function failed 280 of its 14603 tests

История ужасов: стоимость "экономии времени"

Это на самом деле произошло несколько месяцев назад. Гениальный программист решил сэкономить несколько микросекунд за счет вычисления, которое занимало максимум около тридцати секунд, подключив печально известный код "(MidnightOfDateB-MidnightOfDateA)/86400" в нескольких местах. Оптимизация была настолько очевидна, что он даже не задокументировал ее, и оптимизация прошла интеграционные тесты и скрывалась в коде в течение нескольких месяцев, причем все это было незамеченным.

Это произошло в программе, которая рассчитывает заработную плату нескольких продавцов, пользующихся наибольшим спросом, у меньшего из которых ужасное влияние гораздо больше, чем у всей скромной команды программистов из пяти человек вместе взятых. Однажды, несколько месяцев назад, по причинам, которые мало что значат, ошибка произошла - и некоторые из этих ребят получили целый день лишних комиссионных. Они определенно не были удивлены.

Несомненно, они потеряли (и без того очень мало) веру, которую они имели в программе, не предназначенной для того, чтобы тайно их подбросить, и притворились - и получили - полный, подробный обзор кода с тестовыми примерами, выполненными и прокомментированными с точки зрения непрофессионала (плюс много лечения красной ковровой дорожке в следующие недели).

Что я могу сказать: с другой стороны, мы избавились от большого технического долга и смогли переписать и реорганизовать несколько кусочков спагетти-беспорядка, которые были возвращены к заражению КОБОЛОМ в бурные 90-е годы. Программа, несомненно, теперь работает лучше, и там гораздо больше отладочной информации, чтобы быстро сосредоточиться, когда все выглядит подозрительно. Я полагаю, что только эта последняя вещь сэкономит, возможно, один или два человека в месяц в обозримом будущем.

С другой стороны, вся эта затея обошлась компании примерно в 200 000 евро - плюс лицо, плюс, несомненно, некоторая переговорная сила (и, следовательно, еще больше денег).

Парень, ответственный за "оптимизацию", сменил работу год назад, до катастрофы, но все же ходили разговоры, чтобы подать в суд на него за ущерб. И с высшими эшелонами не очень хорошо, что это "последняя ошибка парня" - это выглядело как подстава для нас, чтобы разобраться в этом вопросе, и, в конце концов, мы все еще в конуре и одна из команды планирует выйти.

Девяносто девять раз из ста, "86400 взломать" будет работать безупречно. (Например, в PHP strtotime() будет игнорировать DST и сообщать, что между полуночью последней субботы октября и следующего понедельника прошло ровно 2 * 24 * 60 * 60 секунд, даже если это явно не соответствует действительности... и два блага с радостью сделают одно правым).

Дамы и господа, это был один случай, когда этого не произошло. Как и в случае с подушками безопасности и ремнями безопасности, вам, вероятно, никогда не понадобится сложность (и простота использования) DateTime или Carbon. Но день, когда вы можете (или день, когда вам придется доказать, что вы подумали об этом) ночью придет как вор. Будь готов.

Ответ 7

Объектно-ориентированный стиль:

$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2009-10-13');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%a days');

Процедурный стиль:

$datetime1 = date_create('2009-10-11');
$datetime2 = date_create('2009-10-13');
$interval = date_diff($datetime1, $datetime2);
echo $interval->format('%R%a days');

Ответ 8

Используется следующее:)

$days = (strtotime($endDate) - strtotime($startDate)) / (60 * 60 * 24);
print $days;

Теперь он работает

Ответ 9

Ну, выбранный ответ не самый правильный, потому что он выйдет за пределы UTC. В зависимости от часового пояса (список) могут быть корректировки времени, создающие дни "без" 24 часа, и это сделает расчет (60 * 60 * 24).

Вот пример:

date_default_timezone_set('europe/lisbon');
$time1 = strtotime('2016-03-27');
$time2 = strtotime('2016-03-29');
echo floor( ($time2-$time1) /(60*60*24));
 ^-- the output will be **1**

Итак, правильное решение будет использовать DateTime

date_default_timezone_set('europe/lisbon');
$date1 = new DateTime("2016-03-27");
$date2 = new DateTime("2016-03-29");

echo $date2->diff($date1)->format("%a");
 ^-- the output will be **2**

Ответ 10

$start = '2013-09-08';
$end = '2013-09-15';
$diff = (strtotime($end)- strtotime($start))/24/3600; 
echo $diff;

Ответ 11

Я использую Carbon в моих проектах композитора для этой и подобных целей.

Это было бы так просто:

$dt = Carbon::parse('2010-01-01');
echo $dt->diffInDays(Carbon::now());

Ответ 12

Рассчитайте разницу между двумя датами:

$date1=date_create("2013-03-15");
$date2=date_create("2013-12-12");

$diff=date_diff($date1,$date2);

echo $diff->format("%R%a days");

Выход: +272 дней

Функция date_diff() возвращает разницу между двумя объектами DateTime.

Ответ 13

$datediff = floor(strtotime($date1)/(60*60*24)) - floor(strtotime($date2)/(60*60*24));

и, при необходимости:

$datediff=abs($datediff);

Ответ 14

Если у вас есть время в секундах (отметка времени I.E. unix), вы можете просто вычесть время и разделить на 86400 (секунды в день)

Ответ 15

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

      function dateDiff($date1, $date2)  //days find function
        { 
            $diff = strtotime($date2) - strtotime($date1); 
            return abs(round($diff / 86400)); 
        } 
       //start day
       $date1 = "11-10-2018";        
       // end day
       $date2 = "31-10-2018";    
       // call the days find fun store to variable 
       $dateDiff = dateDiff($date1, $date2); 

       echo "Difference between two dates: ". $dateDiff . " Days "; 

Ответ 16

function howManyDays($startDate,$endDate) {

    $date1  = strtotime($startDate." 0:00:00");
    $date2  = strtotime($endDate." 23:59:59");
    $res    =  (int)(($date2-$date1)/86400);        

return $res;
} 

Ответ 17

Если вы хотите повторить все дни между датой начала и окончания, я придумал следующее:

$startdatum = $_POST['start']; // starting date
$einddatum = $_POST['eind']; // end date

$now = strtotime($startdatum);
$your_date = strtotime($einddatum);
$datediff = $your_date - $now;
$number = floor($datediff/(60*60*24));

for($i=0;$i <= $number; $i++)
{
    echo date('d-m-Y' ,strtotime("+".$i." day"))."<br>";
}

Ответ 18

Вы можете найти даты просто

<?php
$start  = date_create('1988-08-10');
$end    = date_create(); // Current time and date
$diff   = date_diff( $start, $end );

echo 'The difference is ';
echo  $diff->y . ' years, ';
echo  $diff->m . ' months, ';
echo  $diff->d . ' days, ';
echo  $diff->h . ' hours, ';
echo  $diff->i . ' minutes, ';
echo  $diff->s . ' seconds';
// Output: The difference is 28 years, 5 months, 19 days, 20 hours, 34 minutes, 36 seconds

echo 'The difference in days : ' . $diff->days;
// Output: The difference in days : 10398

Ответ 19

Вы можете попробовать код ниже:

$dt1 = strtotime("2019-12-12"); //Enter your first date
$dt2 = strtotime("12-12-2020"); //Enter your second date
echo abs(($dt1 - $dt2) / (60 * 60 * 24));

Ответ 20

    // Change this to the day in the future
$day = 15;

// Change this to the month in the future
$month = 11;

// Change this to the year in the future
$year = 2012;

// $days is the number of days between now and the date in the future
$days = (int)((mktime (0,0,0,$month,$day,$year) - time(void))/86400);

echo "There are $days days until $day/$month/$year";

Ответ 21

Вот моя улучшенная версия, которая показывает 1 год 2 Месяцев 25 дней (ы), если 2-й параметр передан.

class App_Sandbox_String_Util {
    /**
     * Usage: App_Sandbox_String_Util::getDateDiff();
     * @param int $your_date timestamp
     * @param bool $hr human readable. e.g. 1 year(s) 2 day(s)
     * @see http://stackoverflow.com/questions/2040560/finding-the-number-of-days-between-two-dates
     * @see http://qSandbox.com
     */
    static public function getDateDiff($your_date, $hr = 0) {
        $now = time(); // or your date as well
        $datediff = $now - $your_date;
        $days = floor( $datediff / ( 3600 * 24 ) );

        $label = '';

        if ($hr) {
            if ($days >= 365) { // over a year
                $years = floor($days / 365);
                $label .= $years . ' Year(s)';
                $days -= 365 * $years;
            }

            if ($days) {
                $months = floor( $days / 30 );
                $label .= ' ' . $months . ' Month(s)';
                $days -= 30 * $months;
            }

            if ($days) {
                $label .= ' ' . $days . ' day(s)';
            }
        } else {
            $label = $days;
        }

        return $label;
    }
}

Ответ 22

$early_start_date = date2sql($_POST['early_leave_date']);


$date = new DateTime($early_start_date);
$date->modify('+1 day');


$date_a = new DateTime($early_start_date . ' ' . $_POST['start_hr'] . ':' . $_POST['start_mm']);
$date_b = new DateTime($date->format('Y-m-d') . ' ' . $_POST['end_hr'] . ':' . $_POST['end_mm']);

$interval = date_diff($date_a, $date_b);


$time = $interval->format('%h:%i');
$parsed = date_parse($time);
$seconds = $parsed['hour'] * 3600 + $parsed['minute'] * 60;
//        display_error($seconds);

$second3 = $employee_information['shift'] * 60 * 60;

if ($second3 < $seconds)
    display_error(_('Leave time can not be greater than shift time.Please try again........'));
    set_focus('start_hr');
    set_focus('end_hr');
    return FALSE;
}

Ответ 23

<?php
$date1=date_create("2013-03-15");
$date2=date_create("2013-12-12");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");
?>

использовал вышеуказанный код очень просто. Спасибо.

Ответ 24

function get_daydiff($end_date,$today)
{
    if($today=='')
    {
        $today=date('Y-m-d');
    }
    $str = floor(strtotime($end_date)/(60*60*24)) - floor(strtotime($today)/(60*60*24));
    return $str;
}
$d1 = "2018-12-31";
$d2 = "2018-06-06";
echo get_daydiff($d1, $d2);

Ответ 25

Используя эту простую функцию. Объявить функцию

<?php
function dateDiff($firstDate,$secondDate){
    $firstDate = strtotime($firstDate);
    $secondDate = strtotime($secondDate);

    $datediff = $firstDate - $secondDate;
    $output = round($datediff / (60 * 60 * 24));
    return $output;
}
?>

и вызвать эту функцию, как это, где вы хотите

<?php
    echo dateDiff("2018-01-01","2018-12-31");    

// OR

    $firstDate = "2018-01-01";
    $secondDate = "2018-01-01";
    echo dateDiff($firstDate,$secondDate);    
?>

Ответ 26

Самый простой способ найти разницу дней между двумя датами

$date1 = strtotime("2019-05-25"); 
$date2 = strtotime("2010-06-23");

$date_difference = $date2 - $date1;

$result =  round( $date_difference / (60 * 60 * 24) );

echo $result;

Ответ 27

Если вы используете MySql

function daysSince($date, $date2){
$q = "SELECT DATEDIFF('$date','$date2') AS days;";
$result = execQ($q);
$row = mysql_fetch_array($result,MYSQL_BOTH);
return ($row[0]);

}

function execQ($q){
$result = mysql_query( $q);
if(!$result){echo ('Database error execQ' . mysql_error());echo $q;}    
return $result;

}

Ответ 28

Попробуйте использовать Carbon

$d1 = \Carbon\Carbon::now()->subDays(92);
$d2 = \Carbon\Carbon::now()->subDays(10);
$days_btw = $d1->diffInDays($d2);

Также вы можете использовать

\Carbon\Carbon::parse('')

чтобы создать объект Carbon date, используя заданную строку timestamp.

Ответ 29

Это работает!

$start = strtotime('2010-01-25');
$end = strtotime('2010-02-20');

$days_between = ceil(abs($end - $start) / 86400);