developer tip

두 날짜 사이의 일 수 찾기

optionbox 2020. 10. 3. 10:32
반응형

두 날짜 사이의 일 수 찾기


PHP를 사용하여 두 날짜 사이의 일수를 찾는 방법은 무엇입니까?


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

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

을 사용하는 경우 PHP 5.3 >차이를 계산하는 가장 정확한 방법입니다.

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

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

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
)

도움이 되길 바랍니다!


날짜를 유닉스 타임 스탬프로 변환 한 다음 다른 하나를 뺍니다. 이는 초 단위의 차이를 제공하며,이를 86400 (하루의 초 수)으로 나누어 해당 범위의 대략적인 일 수를 제공합니다.

날짜 형식 25.1.201001/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두 날짜 사이의 전체 일수를 얻으려면 대신 사용하십시오 .

날짜가 이미 유닉스 타임 스탬프 형식 인 경우 변환을 건너 뛰고 $days_between일부만 수행 할 수 있습니다 . 좀 더 이국적인 날짜 형식의 경우 올바른 구문 분석을 수행해야 할 수 있습니다.


TL; DRUNIX 타임 스탬프를 사용 하지 않습니다 . 사용하지 마십시오time() . 당신이 경우에, 준비 의 98.0825 %의 신뢰성는 실패한다. DateTime (또는 Carbon)을 사용하십시오.

정답은 Saksham 굽타 (다른 답변도 정확)에 의해 주어진 하나입니다 :

$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)으로 나누는 것이 안전하지 않은 이유

유닉스 타임 스탬프를 사용하여 답변의 대부분 (86400는 일이를 변환하는)와 시나리오로 이어질 수 있습니다, 함께 넣어 두 가정을 만들 잘못된 결과미묘한 버그가 어려울 수 있습니다 추적하고, 며칠, 몇 주 또는 몇 달 후도를 발생 성공적인 배포. 솔루션이 작동하지 않는 것이 아니라 작동합니다. 오늘. 하지만 내일 작동하지 않을 수 있습니다.

첫 번째 실수는 "어제 이후 며칠이 지났습니까?"라는 질문 에 현재와 "어제"로 표시된 순간 사이에 하루지나지 않은 경우 컴퓨터가 0으로 답할 수 있다는 점을 고려하지 않는 입니다.

일반적으로 "일"을 UNIX 타임 스탬프로 변환 할 때 얻은 것은 특정 날짜 자정대한 타임 스탬프 입니다.

따라서 10 월 1 일 자정과 10 월 15 일 사이에 15 일이 경과했습니다. 그러나 10 월 1 일 13:00부터 10 월 15 일 14:55까지 15 일에서 5 분뺀 시간지났 으며 floor()암시 적 정수 변환을 사용 하거나 수행하는 대부분의 솔루션 은 예상보다 하루가 적게보고됩니다 .

그럼 "Ymd H : i : s는 며칠 전 이었나요?" 수율 것이다 틀린 답을 .

두 번째 실수는 하루를 86400 초와 동일시하는 것입니다. 이것은 거의 항상 사실입니다. 그렇지 않은 경우를 간과 할만큼 자주 발생합니다. 그러나 두 개의 연속 midnights 사이의 시간 (초)의 거리이다 확실히 일광 시간 절약이 활동하기 시작하는 때 적어도하지 86400 년에 두 번. DST 경계에서 두 날짜를 비교하면 잘못된 답을 얻을 수 있습니다.

따라서 모든 날짜 타임 스탬프를 고정 된 시간으로 강제하는 "해킹"을 사용하더라도 자정이라고 말하십시오 (이것은 또한 시간-분-초가 아닌 일-월-년만 지정하는 경우 다양한 언어 및 프레임 워크에 의해 암시 적으로 수행됩니다. MySQL과 같은 데이터베이스에서 DATE 유형과 동일), 널리 사용되는 공식

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

또는

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

예를 들어, DATE1과 DATE2가 같은 해의 DST 세그먼트에 있으면 17을 반환합니다. 그러나 17.042를 반환 할 수 있으며 더 나쁜 경우 16.958을 반환 할 수 있습니다. 의 사용 층 () 다음 있었어야 변환합니다 또는 정수에 대한 암시 적 절단은 다른 상황에서, 16 17, 같은 표현 "$ 일> 17"반환 true이 나타내는 경우에도 17.042 동안 그 경과 일 수 18 세입니다.

일부는 윤초를 적용하고 일부는 적용하지 않을 수 있기 때문에 이러한 코드 플랫폼간에 이식 할 수 없기 때문에 상황은 더욱 추악 해 집니다. 수행 하는 플랫폼 에서 두 날짜의 차이는 86400이 아니라 86401 또는 86399 일 것입니다. 따라서 5 월에 작동했고 실제로 모든 테스트를 통과 한 코드는 다음 6 월에 중단됩니다. 12.99999 일이 13 일 대신 12 일로 간주됩니다. 두 날짜 2015 년에 작동 한 것은 2017 년에는 작동하지 않을 것입니다. 같은 날짜에, 어느해도 윤년이 아닙니다. 그러나 2018-03-01과 2017-03-01 사이에 관심있는 플랫폼에서 365 일이 아닌 366 일이지나 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간에 변환하십시오. 당신은 것입니다 항상 이십에 대한 시간의 나머지를 얻을. 이것은 21 시간 또는 19, 어쩌면 18 시간 59 분 36 초가 될 수 있습니다. 문제 없어. 그것은 거기에 머무르고 가까운 미래에 긍정적으로 유지 될 큰 마진 입니다. 이제floor() 안전하게 자를 수 있습니다 .

그러나 마법 상수, 반올림 클러 지 및 유지 관리 부채를 피하기 위한 올바른 해결책은 다음과 같습니다.

  • 시간 라이브러리 (Datetime, Carbon 등)를 사용합니다. 자신을 굴리지 마십시오

  • DST 경계, 윤년, 윤초 등의 일반적인 날짜뿐만 아니라 정말 나쁜 날짜 선택을 사용하여 포괄적 인 테스트 케이스작성 합니다. 이상적으로는 (datetime에 대한 호출이 빠릅니다 !) 문자열에서 순차적으로 조합하여 4 년 (1 일)에 해당하는 날짜를 생성하고 테스트되는 첫날과 테스트되는 날의 차이가 1 씩 꾸준히 증가하는지 확인합니다. 이것은 낮은 수준의 루틴과 도약 초에서 아무것도 변경하는 경우 보장합니다 수정 과시을 파괴하려고, 적어도 당신은 것 알고있다 .

  • 나머지 테스트 스위트와 함께 이러한 테스트를 정기적으로 실행하십시오. 수 밀리 초의 문제이며 문자 그대로 머리를 긁는 데 드는 시간절약 할 수 있습니다 .


솔루션이 무엇이든 테스트하십시오!

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"코드를 여러 곳에 연결하여 최대 약 30 초가 걸리는 계산에서 몇 마이크로 초를 절약하기로 결정했습니다. 그가 문서화조차하지 않은 최적화가 너무나 명백했고, 최적화는 통합 테스트를 통과하고 몇 달 동안 코드에 숨어 있었는데 모두 눈에 띄지 않았습니다.

이것은 몇 명의 베스트셀러 세일즈맨의 임금을 계산하는 프로그램에서 일어났습니다. 그 중 가장 적은 것은 5 명으로 구성된 겸손한 프로그래머 팀 전체를 합친 것보다 훨씬 더 영향력이 있습니다. 몇 달 전 어느 날, 그다지 중요하지 않은 이유로 버그가 발생했습니다. 중 일부 는 하루 종일 큰 수수료를받지 못했습니다. 그들은 확실히 즐겁지 않았습니다 .

무한 악화, 그들은 (이미 거의) 믿음들이이 프로그램에 한 손실 되지 및 - 몰래 그들을 샤프트 설계 및 척하고 얻을 - 테스트 케이스와 완벽한 상세 코드 리뷰가 실행하고 평신도의 관점에서 주석 (플러스 많이 다음 주에 레드 카펫 치료).

내가 말할 수있는 것은 : 플러스 측면에서, 우리는 많은 기술적 부채를 없 앴고, 90 년대 흔들리는 COBOL 감염으로 되돌아가는 스파게티 엉망의 여러 조각을 다시 작성하고 리팩토링 할 수있었습니다. 프로그램은 의심 할 여지없이 이제 더 잘 실행되며, 이상하게 보일 때 신속하게 제로화 할 수있는 디버깅 정보가 훨씬 많습니다. 나는이 마지막 한 가지만으로 가까운 장래에 한 달에 하루나 이틀의 인력을 절약 할 수있을 것으로 예상합니다.

마이너스 측면에서 전체 brouhaha는 회사에 약 € 200,000의 비용을 지불했습니다.

"최적화"를 담당 한 사람은 재난이 발생하기 1 년 전에 직장을 바꿨지 만 여전히 손해 배상 소송을 제기 할 수있는 대화가있었습니다. 그리고 그것이 "마지막 녀석의 잘못"이라는 것은 상위 계층과 잘 어울리지 않았습니다. 그것은 우리가 문제를 해결하기위한 설정처럼 보였고 결국 우리는 여전히 개집에 있습니다. 팀 중 한 명이 그만두려고합니다.

100 번 중 99 번은 "86400 핵"이 완벽하게 작동합니다. (예를 들어 PHP에서 strtotime()DST를 무시하고 10 월 마지막 토요일 자정과 다음 월요일 자정 사이에 분명히 사실 이 아니더라도 정확히 2 * 24 * 60 * 60 초가 지났다고보고 합니다 . 두 가지 잘못이 기꺼이 하나를 바로 잡을 것입니다).

신사 숙녀 여러분, 그렇지 않은 경우 하나 있습니다. 에어백 및 안전 벨트와 마찬가지로 또는 의 복잡성 (및 사용 용이성)이 실제로 필요 하지 않을 것입니다 . 그러나 당신 있는 날 (또는 당신이 이것에 대해 생각 했다는 것을 증명해야)은 밤에 도둑으로 올 것입니다. 준비하십시오.DateTimeCarbon


사용하기 쉬운 date_diff

$from=date_create(date('Y-m-d'));
$to=date_create("2013-03-15");
$diff=date_diff($to,$from);
print_r($diff);
echo $diff->format('%R%a days');

객체 지향 스타일 :

$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');

이것을 사용했습니다 :)

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

이제 작동합니다


글쎄, 선택한 답변은 UTC 외부에서 실패하기 때문에 가장 정확한 답변이 아닙니다. 시간대 ( list ) 에 따라 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**

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

나는 이것과 비슷한 목적으로 작곡가 프로젝트에서 Carbon사용 하고 있습니다.

다음과 같이 쉽습니다.

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

두 날짜의 차이를 계산하십시오.

$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 객체 간의 차이를 반환합니다.


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

그리고 필요한 경우 :

$datediff=abs($datediff);

초 단위의 시간 (IE unix 타임 스탬프)이 있으면 시간을 빼고 86400 (하루에 초)으로 나눌 수 있습니다.


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 "; 

function howManyDays($startDate,$endDate) {

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

return $res;
} 

시작일과 종료일 사이의 모든 날을 에코하고 싶다면 다음과 같이 생각해 냈습니다.

$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>";
}

간단하게 날짜를 찾을 수 있습니다.

<?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

아래 코드를 시도해 볼 수 있습니다.

$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));

    // 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";

다음은 두 번째 매개 변수가 전달되면 1 년 2 개월 25 일을 보여주는 개선 된 버전입니다.

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;
    }
}

$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;
}

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

위의 코드를 매우 간단하게 사용했습니다. 감사.


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);

이 간단한 기능을 사용합니다. 함수 선언

<?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);    
?>

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;

}


Carbon 사용해보기

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

또한 사용할 수 있습니다

\Carbon\Carbon::parse('')

주어진 타임 스탬프 문자열을 사용하여 Carbon 날짜의 객체를 생성합니다.


작동합니다!

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

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

참고 URL : https://stackoverflow.com/questions/2040560/finding-the-number-of-days-between-two-dates

반응형