PHP를 사용하여 두 날짜의 차이를 계산하는 방법은 무엇입니까?


722

양식의 두 날짜가 있습니다.

Start Date: 2007-03-24 
End Date: 2009-06-26

이제 다음 두 형식의 차이점을 찾아야합니다.

2 years, 3 months and 2 days

PHP에서 어떻게해야합니까?


1
2 년 94 일 윤년을 고려하여 월을 계산하는 것은 문제가 될 수 있습니다. 이것이 얼마나 정확해야합니까?
dbasnett

답변:


526

레거시 코드 (PHP <5.3)에 사용하십시오. 최신 솔루션은 아래 jurka의 답변을 참조하십시오

strtotime ()을 사용하여 두 날짜를 유닉스 시간으로 변환 한 다음 그 사이의 초 수를 계산할 수 있습니다. 이것으로부터 다른 기간을 계산하는 것이 다소 쉽습니다.

$date1 = "2007-03-24";
$date2 = "2009-06-26";

$diff = abs(strtotime($date2) - strtotime($date1));

$years = floor($diff / (365*60*60*24));
$months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
$days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));

printf("%d years, %d months, %d days\n", $years, $months, $days);

편집 : 분명히이 작업을 수행하는 바람직한 방법은 아래의 jurka와 같습니다. 내 코드는 일반적으로 PHP 5.3 이상이없는 경우에만 권장됩니다.

의견의 일부 사람들은 위의 코드가 단지 근사치라고 지적했습니다. 나는 범위의 사용법이 정밀도를 제공하기보다 시간이 지났거나 남아있는 시간의 감각을 제공하는 것이 더 낫기 때문에 대부분의 목적에는 문제가 없다고 생각합니다. 그렇게하려면 날짜를 출력하십시오.

그럼에도 불구하고, 나는 불만을 해결하기로 결정했습니다. 정확한 범위가 필요하지만 PHP 5.3에 액세스 할 수없는 경우 아래 코드를 사용하십시오 (PHP 4에서도 작동 함). 일광 절약 시간을 고려하지 않은 경우를 제외하고는 PHP가 내부적으로 범위를 계산하기 위해 사용하는 코드의 직접 포트입니다. 즉, 최대 1 시간이 지났지 만 그 외에는 정확해야합니다.

<?php

/**
 * Calculate differences between two dates with precise semantics. Based on PHPs DateTime::diff()
 * implementation by Derick Rethans. Ported to PHP by Emil H, 2011-05-02. No rights reserved.
 * 
 * See here for original code:
 * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/tm2unixtime.c?revision=302890&view=markup
 * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/interval.c?revision=298973&view=markup
 */

function _date_range_limit($start, $end, $adj, $a, $b, $result)
{
    if ($result[$a] < $start) {
        $result[$b] -= intval(($start - $result[$a] - 1) / $adj) + 1;
        $result[$a] += $adj * intval(($start - $result[$a] - 1) / $adj + 1);
    }

    if ($result[$a] >= $end) {
        $result[$b] += intval($result[$a] / $adj);
        $result[$a] -= $adj * intval($result[$a] / $adj);
    }

    return $result;
}

function _date_range_limit_days($base, $result)
{
    $days_in_month_leap = array(31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    $days_in_month = array(31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

    _date_range_limit(1, 13, 12, "m", "y", &$base);

    $year = $base["y"];
    $month = $base["m"];

    if (!$result["invert"]) {
        while ($result["d"] < 0) {
            $month--;
            if ($month < 1) {
                $month += 12;
                $year--;
            }

            $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
            $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];

            $result["d"] += $days;
            $result["m"]--;
        }
    } else {
        while ($result["d"] < 0) {
            $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0);
            $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month];

            $result["d"] += $days;
            $result["m"]--;

            $month++;
            if ($month > 12) {
                $month -= 12;
                $year++;
            }
        }
    }

    return $result;
}

function _date_normalize($base, $result)
{
    $result = _date_range_limit(0, 60, 60, "s", "i", $result);
    $result = _date_range_limit(0, 60, 60, "i", "h", $result);
    $result = _date_range_limit(0, 24, 24, "h", "d", $result);
    $result = _date_range_limit(0, 12, 12, "m", "y", $result);

    $result = _date_range_limit_days(&$base, &$result);

    $result = _date_range_limit(0, 12, 12, "m", "y", $result);

    return $result;
}

/**
 * Accepts two unix timestamps.
 */
function _date_diff($one, $two)
{
    $invert = false;
    if ($one > $two) {
        list($one, $two) = array($two, $one);
        $invert = true;
    }

    $key = array("y", "m", "d", "h", "i", "s");
    $a = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $one))));
    $b = array_combine($key, array_map("intval", explode(" ", date("Y m d H i s", $two))));

    $result = array();
    $result["y"] = $b["y"] - $a["y"];
    $result["m"] = $b["m"] - $a["m"];
    $result["d"] = $b["d"] - $a["d"];
    $result["h"] = $b["h"] - $a["h"];
    $result["i"] = $b["i"] - $a["i"];
    $result["s"] = $b["s"] - $a["s"];
    $result["invert"] = $invert ? 1 : 0;
    $result["days"] = intval(abs(($one - $two)/86400));

    if ($invert) {
        _date_normalize(&$a, &$result);
    } else {
        _date_normalize(&$b, &$result);
    }

    return $result;
}

$date = "1986-11-10 19:37:22";

print_r(_date_diff(strtotime($date), time()));
print_r(_date_diff(time(), strtotime($date)));

1
DateTime 클래스를 사용하는 경우 $ date-> format ( 'U')로 이동하여 유닉스 타임 스탬프를 얻을 수 있습니다.
Jon Cram

4
여름 / 겨울 시간을 처리해야한다면 사실이 아닙니다. 이 특정 여름 / 겨울 시간을 조정할 때 하루는 23 시간 또는 25 시간입니다.
Arno

4
윤년에도 같은 주장을 할 수 있습니다. 그것도 고려하지 않습니다. 아직도, 나는 우리가 여기서 범위를 논의하고 있기 때문에 당신이 그것을 고려하고 싶다고 확신하지 않습니다. 범위의 의미는 절대 날짜와 약간 다릅니다.
Emil H

9
이 기능이 잘못되었습니다. 근사값에는 좋지만 정확한 범위에는 맞지 않습니다. 예를 들어, 한 달에 30 일이 있다고 가정합니다. 즉, 2 월 1 일에서 3 월 1 일 사이에 7 월 1 일에서 8 월 1 일 (윤년에 관계없이)과 동일한 날짜 차이가있을 것입니다.
enobrev

1
PHP에서 참조 변수는 호출이 아니라 함수 서명에 있습니다. 모든 &서명을 서명으로 옮깁니다.
Paul Tarjan

909

DateTime 및 DateInterval 개체를 사용하는 것이 좋습니다.

$date1 = new DateTime("2007-03-24");
$date2 = new DateTime("2009-06-26");
$interval = $date1->diff($date2);
echo "difference " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days "; 

// shows the total amount of days (not divided into years, months and days like above)
echo "difference " . $interval->days . " days ";

더 읽어보기 PHP DateTime :: diff manual

매뉴얼에서 :

PHP 5.2.2부터는 DateTime 객체를 비교 연산자를 사용하여 비교할 수 있습니다.

$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");

var_dump($date1 == $date2); // bool(false)
var_dump($date1 < $date2);  // bool(true)
var_dump($date1 > $date2);  // bool(false)

14
+1 DateTime은 윤년과 시간대를 올바르게 처리하며 선반을위한 좋은 책이 있습니다 : phparch.com/books/…
hakre

3
두 DateTime 사이의 총 시간 (초)을 제공하는 방법이 있습니까? (구성 요소를 추가하지 않고)
potatoe

1
@Panique $ interval-> days와 $ interval-> d는 다른 측정 값입니다. 귀하의 위 의견이 맞습니다. "위의 총 일수 (위와 같이 년, 월, 일로 나뉘 지 않음)를 표시합니다"
jurka

1
@potatoe 아마도 원할 것입니다 $date2->format('U') - $date1->format('U').
Paulo Freitas

3
Windows에서 일부 PHP 버전의 DateInterval 에 잘못된 days 속성 ( 항상 6015 ) 이있는 버그가 있습니다. bugs.php.net/bug.php?id=51184 (수정 / 해결 방법에 대한 의견 참조)
Pim Schaaf

73

가장 좋은 방법은 PHP DateTime(및 DateInterval) 객체를 사용하는 것입니다. 각 날짜는 DateTime개체에 캡슐화되어 있으며 두 날짜 사이에 차이가 생길 수 있습니다.

$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");

DateTime객체는 모든 형식가 받아들이는 strtotime()것입니다. 보다 구체적인 날짜 형식이 필요한 DateTime::createFromFormat()경우 DateTime개체 를 만드는 데 사용할 수 있습니다 .

두 객체가 인스턴스화되면을 사용하여 하나를 다른 것에서 뺍니다 DateTime::diff().

$difference = $first_date->diff($second_date);

$difference이제 DateInterval차이 정보 가있는 객체를 보유합니다 . A var_dump()는 다음과 같습니다

object(DateInterval)
  public 'y' => int 0
  public 'm' => int 0
  public 'd' => int 20
  public 'h' => int 6
  public 'i' => int 56
  public 's' => int 30
  public 'invert' => int 0
  public 'days' => int 20

DateInterval객체의 형식을 지정하려면 각 값을 확인하고 0 인 경우 제외해야합니다.

/**
 * Format an interval to show all existing components.
 * If the interval doesn't have a time component (years, months, etc)
 * That component won't be displayed.
 *
 * @param DateInterval $interval The interval
 *
 * @return string Formatted interval string.
 */
function format_interval(DateInterval $interval) {
    $result = "";
    if ($interval->y) { $result .= $interval->format("%y years "); }
    if ($interval->m) { $result .= $interval->format("%m months "); }
    if ($interval->d) { $result .= $interval->format("%d days "); }
    if ($interval->h) { $result .= $interval->format("%h hours "); }
    if ($interval->i) { $result .= $interval->format("%i minutes "); }
    if ($interval->s) { $result .= $interval->format("%s seconds "); }

    return $result;
}

이제 남은 것은 $difference DateInterval객체에서 함수를 호출하는 것입니다.

echo format_interval($difference);

그리고 우리는 올바른 결과를 얻습니다.

20 일 6 시간 56 분 30 초

목표를 달성하는 데 사용 된 완전한 코드 :

/**
 * Format an interval to show all existing components.
 * If the interval doesn't have a time component (years, months, etc)
 * That component won't be displayed.
 *
 * @param DateInterval $interval The interval
 *
 * @return string Formatted interval string.
 */
function format_interval(DateInterval $interval) {
    $result = "";
    if ($interval->y) { $result .= $interval->format("%y years "); }
    if ($interval->m) { $result .= $interval->format("%m months "); }
    if ($interval->d) { $result .= $interval->format("%d days "); }
    if ($interval->h) { $result .= $interval->format("%h hours "); }
    if ($interval->i) { $result .= $interval->format("%i minutes "); }
    if ($interval->s) { $result .= $interval->format("%s seconds "); }

    return $result;
}

$first_date = new DateTime("2012-11-30 17:03:30");
$second_date = new DateTime("2012-12-21 00:00:00");

$difference = $first_date->diff($second_date);

echo format_interval($difference);

DateTime()함수가 아니며, 객체이며, PHP 5.2부터 존재합니다. 서버가이를 지원하는지 확인하십시오.
Madara의 유령

2
@SecondRikudo DateTime :: Diff 는 PHP 5.3.0 필요
PhoneixS

first_date를 second_date로 교환하는데 문제가 있는데 같은 결과를 얻습니까? 0 일 0 시간 0 분 0 초 또는 0만을 말하지 않는 이유 : 예 : 2012-11-30 17:03:30-2012-12-21 00:00:00 및 2012-12-21 00:00:00- 2012-11-30 17:03:30 동일한 결과를 얻습니다.
EgoistDeveloper

diff는 두 시간의 차이를 제공하기 때문입니다. 차후의 날짜에 관계없이 차이는 0이 아닙니다.
Madara의 유령

1
시간이 많이 걸리지 않고 코드베이스의 어느 곳에서나 호출 할 수있는 명확한 기능을 제공하기 때문에 이것은 정말 좋은 대답입니다. 다른 답변을 사용하면 문제를 해결하기보다는 증상을 해결하는 반향을 불러 일으킬 수 있습니다. 내가 추가 한 유일한 요소 (그리고 거의 모든 다른 게시물은 이것을 다루지 않습니다)는 $ interval 요소의 복수입니다
nickhar

33

시간 및 분과 초보기 ..

$date1 = "2008-11-01 22:45:00"; 

$date2 = "2009-12-04 13:44:01"; 

$diff = abs(strtotime($date2) - strtotime($date1)); 

$years   = floor($diff / (365*60*60*24)); 
$months  = floor(($diff - $years * 365*60*60*24) / (30*60*60*24)); 
$days    = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));

$hours   = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24)/ (60*60)); 

$minuts  = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60)/ 60); 

$seconds = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60 - $minuts*60)); 

printf("%d years, %d months, %d days, %d hours, %d minuts\n, %d seconds\n", $years, $months, $days, $hours, $minuts, $seconds); 

7
아마도 이것은 정확한 결과를 얻지 못할 것입니다.
돌고래 돌고래

8
끔찍하게 구식 인 PHP 버전을 사용하지 않으면 끔찍한 해결책입니다.
rdlowrey

2
너무 건조 하지 않습니다 . 예를 들어 60 * 60 * 24는 15 번 반복됩니다. 긴 라이브 복사-붙여 넣기 재사용!
Peter Mortensen

윤년은 어떻습니까? 년은 평균 365 일이 아닙니다.
Peter Mortensen

이 코드는 한 달이 평균 30 일이라고 가정합니다. 1 년 365 일을 가정하더라도 평균 월은 365/12 = 30.42 일 (약)입니다.
Peter Mortensen

18

다음 링크를보십시오. 이것은 내가 지금까지 찾은 최고의 답변입니다 .. :)

function dateDiff ($d1, $d2) {

    // Return the number of days between the two dates:    
    return round(abs(strtotime($d1) - strtotime($d2))/86400);

} // end function dateDiff

날짜 매개 변수를 전달할 때 어떤 날짜가 더 빠르거나 늦은지는 중요하지 않습니다. 이 함수는 PHP ABS () 절대 값을 사용하여 항상 두 날짜 사이의 일 수로 postive 숫자를 반환합니다.

두 날짜 사이의 날짜 수는 두 날짜를 모두 포함하지는 않습니다. 따라서 입력 한 날짜와 그 사이의 모든 날짜로 표시되는 일 수를 찾으려면이 함수의 결과에 1을 추가해야합니다.

예를 들어, 2013-02-09와 2013-02-14의 차이 (위 함수에서 반환)는 5입니다. 그러나 날짜 범위 2013-02-09-2013-02- 14는 6입니다.

http://www.bizinfosys.com/php/date-difference.html


질문은 총 일수가 아닌 연도, 월, 일 수의 차이를 요구했습니다.
Peter Mortensen

14

내가 가장 좋아하는 jurka답변에 투표 했지만 pre-php.5.3 버전이 있습니다 ...

나는 비슷한 문제를 겪고 있다는 것을 알았습니다.이 질문에 처음으로 도달 한 방법입니다. 그러나 내 기능 으로이 문제를 꽤 잘 해결했으며 내 라이브러리의 어느 곳에도 잃어 버리지 않고 잊어 버리지 않는 곳에 보관할 수 없으므로 누군가에게 유용하기를 바랍니다.

/**
 *
 * @param DateTime $oDate1
 * @param DateTime $oDate2
 * @return array 
 */
function date_diff_array(DateTime $oDate1, DateTime $oDate2) {
    $aIntervals = array(
        'year'   => 0,
        'month'  => 0,
        'week'   => 0,
        'day'    => 0,
        'hour'   => 0,
        'minute' => 0,
        'second' => 0,
    );

    foreach($aIntervals as $sInterval => &$iInterval) {
        while($oDate1 <= $oDate2){ 
            $oDate1->modify('+1 ' . $sInterval);
            if ($oDate1 > $oDate2) {
                $oDate1->modify('-1 ' . $sInterval);
                break;
            } else {
                $iInterval++;
            }
        }
    }

    return $aIntervals;
}

그리고 테스트 :

$oDate = new DateTime();
$oDate->modify('+111402189 seconds');
var_dump($oDate);
var_dump(date_diff_array(new DateTime(), $oDate));

그리고 결과 :

object(DateTime)[2]
  public 'date' => string '2014-04-29 18:52:51' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'America/New_York' (length=16)

array
  'year'   => int 3
  'month'  => int 6
  'week'   => int 1
  'day'    => int 4
  'hour'   => int 9
  'minute' => int 3
  'second' => int 8

나는 여기 에서 원래의 아이디어를 얻었고, 나는 그것을 나의 용도로 수정했다.

원하지 않는 간격 (예 : "주")을 $aIntervals배열 에서 제거 하거나 $aExclude매개 변수를 추가 하거나 문자열을 출력 할 때 필터링하여 쉽게 제거 할 수 있습니다.


불행히도 이것은 년 / 월 오버플로로 인해 DateInterval과 동일한 것을 반환하지 않습니다.
Stephen Harris

2
@StephenHarris : 이것을 테스트하지는 않았지만 코드를 읽음으로써 week인덱스 를 삭제하면 $aIntervals(같은 DateDiff것을 사용하지 않기 때문에) 동일한 결과를 반환해야한다고 확신합니다 .
Alix Axel

이것은 두 날짜 사이의 모든 간격에서 발생하는 날짜를 찾기위한 훌륭한 솔루션입니다.
betweenbrain

14
<?php
    $today = strtotime("2011-02-03 00:00:00");
    $myBirthDate = strtotime("1964-10-30 00:00:00");
    printf("Days since my birthday: ", ($today - $myBirthDate)/60/60/24);
?>

질문은 , , 수의 차이를 요구했다 . 이 차이를 총 일 수로 출력합니다.
Peter Mortensen

11

PHP 프레임 워크를 사용하고 있는지 여부는 알 수 없지만 많은 PHP 프레임 워크에는 날짜 / 시간 라이브러리와 도우미가있어 바퀴를 재발 명하지 못하게합니다.

예를 들어 CodeIgniter에는 timespan()기능이 있습니다. 두 개의 Unix 타임 스탬프를 입력하면 다음과 같은 결과가 자동으로 생성됩니다.

1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes

http://codeigniter.com/user_guide/helpers/date_helper.html


8

사용 예 :

echo time_diff_string('2013-05-01 00:22:35', 'now');
echo time_diff_string('2013-05-01 00:22:35', 'now', true);

출력 :

4 months ago
4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago

함수 :

function time_diff_string($from, $to, $full = false) {
    $from = new DateTime($from);
    $to = new DateTime($to);
    $diff = $to->diff($from);

    $diff->w = floor($diff->d / 7);
    $diff->d -= $diff->w * 7;

    $string = array(
        'y' => 'year',
        'm' => 'month',
        'w' => 'week',
        'd' => 'day',
        'h' => 'hour',
        'i' => 'minute',
        's' => 'second',
    );
    foreach ($string as $k => &$v) {
        if ($diff->$k) {
            $v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
        } else {
            unset($string[$k]);
        }
    }

    if (!$full) $string = array_slice($string, 0, 1);
    return $string ? implode(', ', $string) . ' ago' : 'just now';
}

차이가 30 분보다 큰지 확인하려면 어떻게해야합니까?
Ofir Attia

@ OfirAttia : 여기에 많은 질문이 있으므로 검색을 사용하십시오. 간단한 데모
Glavić

7

나는 그것에 대한 간단한 논리가 있습니다.

<?php
    per_days_diff('2011-12-12','2011-12-29')
    function per_days_diff($start_date, $end_date) {
        $per_days = 0;
        $noOfWeek = 0;
        $noOfWeekEnd = 0;
        $highSeason=array("7", "8");

        $current_date = strtotime($start_date);
        $current_date += (24 * 3600);
        $end_date = strtotime($end_date);

        $seassion = (in_array(date('m', $current_date), $highSeason))?"2":"1";

        $noOfdays = array('');

        while ($current_date <= $end_date) {
            if ($current_date <= $end_date) {
                $date = date('N', $current_date);
                array_push($noOfdays,$date);
                $current_date = strtotime('+1 day', $current_date);
            }
        }

        $finalDays = array_shift($noOfdays);
        //print_r($noOfdays);
        $weekFirst = array("week"=>array(),"weekEnd"=>array());
        for($i = 0; $i < count($noOfdays); $i++)
        {
            if ($noOfdays[$i] == 1)
            {
                //echo "This is week";
                //echo "<br/>";
                if($noOfdays[$i+6]==7)
                {
                    $noOfWeek++;
                    $i=$i+6;
                }
                else
                {
                    $per_days++;
                }
                //array_push($weekFirst["week"],$day);
            }
            else if($noOfdays[$i]==5)
            {
                //echo "This is weekend";
                //echo "<br/>";
                if($noOfdays[$i+2] ==7)
                {
                    $noOfWeekEnd++;
                    $i = $i+2;
                }
                else
                {
                    $per_days++;
                }
                //echo "After weekend value:- ".$i;
                //echo "<br/>";
            }
            else
            {
                $per_days++;
            }
        }

        /*echo $noOfWeek;
          echo "<br/>";
          echo $noOfWeekEnd;
          echo "<br/>";
          print_r($per_days);
          echo "<br/>";
          print_r($weekFirst);
        */

        $duration = array("weeks"=>$noOfWeek, "weekends"=>$noOfWeekEnd, "perDay"=>$per_days, "seassion"=>$seassion);
        return $duration;
      ?>

샘플 코드의 끝에 누락 된 것이있는 것 같습니다 (끝 괄호 및 " ?> "?).
Peter Mortensen

"간단한"논리. 40 줄 이상의 순수 코드입니다.
Madjosz

6

당신은 사용할 수 있습니다

getdate()

제공된 날짜 / 시간의 모든 요소를 ​​포함하는 배열을 반환하는 함수 :

$diff = abs($endDate - $startDate);
$my_t=getdate($diff);
print("$my_t[year] years, $my_t[month] months and $my_t[mday] days");

시작 날짜와 종료 날짜가 문자열 형식 인 경우

$startDate = strtotime($startDateStr);
$endDate = strtotime($endDateStr);

위의 코드 전에


작동하지 않는 것 같습니다. 타임 스탬프 시대가 시작될 때 날짜를 얻습니다.
Sirber

$my_t["year"] -= 1970올바른 연도를 얻으려면를 해야한다는 것을 이해하는 것이 중요합니다 . 또한 시간을 올바르게 얻으려면 GMT에서 시차 를 빼야 합니다 . 월과 날짜에서 1을 빼야합니다.
살만 A

6
// If you just want to see the year difference then use this function.
// Using the logic I've created you may also create month and day difference
// which I did not provide here so you may have the efforts to use your brain.
// :)
$date1='2009-01-01';
$date2='2010-01-01';
echo getYearDifference ($date1,$date2);
function getYearDifference($date1=strtotime($date1),$date2=strtotime($date2)){
    $year = 0;
    while($date2 > $date1 = strtotime('+1 year', $date1)){
        ++$year;
    }
    return $year;
}

"strtotime ( '+ 1 year', $ date1)"은 윤년을 고려합니까?
Peter Mortensen

6

이것은 내 기능입니다. 필수 PHP> = 5.3.4. DateTime 클래스를 사용합니다. 매우 빠르고 빠르며 두 날짜 또는 이른바 "시간 이후"사이의 차이를 수행 할 수 있습니다.

if(function_exists('grk_Datetime_Since') === FALSE){
    function grk_Datetime_Since($From, $To='', $Prefix='', $Suffix=' ago', $Words=array()){
        #   Est-ce qu'on calcul jusqu'à un moment précis ? Probablement pas, on utilise maintenant
        if(empty($To) === TRUE){
            $To = time();
        }

        #   On va s'assurer que $From est numérique
        if(is_int($From) === FALSE){
            $From = strtotime($From);
        };

        #   On va s'assurer que $To est numérique
        if(is_int($To) === FALSE){
            $To = strtotime($To);
        }

        #   On a une erreur ?
        if($From === FALSE OR $From === -1 OR $To === FALSE OR $To === -1){
            return FALSE;
        }

        #   On va créer deux objets de date
        $From = new DateTime(@date('Y-m-d H:i:s', $From), new DateTimeZone('GMT'));
        $To   = new DateTime(@date('Y-m-d H:i:s', $To), new DateTimeZone('GMT'));

        #   On va calculer la différence entre $From et $To
        if(($Diff = $From->diff($To)) === FALSE){
            return FALSE;
        }

        #   On va merger le tableau des noms (par défaut, anglais)
        $Words = array_merge(array(
            'year'      => 'year',
            'years'     => 'years',
            'month'     => 'month',
            'months'    => 'months',
            'week'      => 'week',
            'weeks'     => 'weeks',
            'day'       => 'day',
            'days'      => 'days',
            'hour'      => 'hour',
            'hours'     => 'hours',
            'minute'    => 'minute',
            'minutes'   => 'minutes',
            'second'    => 'second',
            'seconds'   => 'seconds'
        ), $Words);

        #   On va créer la chaîne maintenant
        if($Diff->y > 1){
            $Text = $Diff->y.' '.$Words['years'];
        } elseif($Diff->y == 1){
            $Text = '1 '.$Words['year'];
        } elseif($Diff->m > 1){
            $Text = $Diff->m.' '.$Words['months'];
        } elseif($Diff->m == 1){
            $Text = '1 '.$Words['month'];
        } elseif($Diff->d > 7){
            $Text = ceil($Diff->d/7).' '.$Words['weeks'];
        } elseif($Diff->d == 7){
            $Text = '1 '.$Words['week'];
        } elseif($Diff->d > 1){
            $Text = $Diff->d.' '.$Words['days'];
        } elseif($Diff->d == 1){
            $Text = '1 '.$Words['day'];
        } elseif($Diff->h > 1){
            $Text = $Diff->h.' '.$Words['hours'];
        } elseif($Diff->h == 1){
            $Text = '1 '.$Words['hour'];
        } elseif($Diff->i > 1){
            $Text = $Diff->i.' '.$Words['minutes'];
        } elseif($Diff->i == 1){
            $Text = '1 '.$Words['minute'];
        } elseif($Diff->s > 1){
            $Text = $Diff->s.' '.$Words['seconds'];
        } else {
            $Text = '1 '.$Words['second'];
        }

        return $Prefix.$Text.$Suffix;
    }
}

6

나는 사용 date_create하고 date_diff객체를 선호 합니다.

암호:

$date1 = date_create("2007-03-24");
$date2 = date_create("2009-06-26");

$dateDifference = date_diff($date1, $date2)->format('%y years, %m months and %d days');

echo $dateDifference;

산출:

2 years, 3 months and 2 days

자세한 정보는 PHP 매뉴얼을 읽으십시오date_diff

매뉴얼에 따르면 DateTime :: diff ()date_diff 의 별칭입니다.


5

타임 스탬프가 제공되었는지 여부를 감지하고 미래의 날짜 / 시간을 음수 값으로 반환합니다.

<?php

function time_diff($start, $end = NULL, $convert_to_timestamp = FALSE) {
  // If $convert_to_timestamp is not explicitly set to TRUE,
  // check to see if it was accidental:
  if ($convert_to_timestamp || !is_numeric($start)) {
    // If $convert_to_timestamp is TRUE, convert to timestamp:
    $timestamp_start = strtotime($start);
  }
  else {
    // Otherwise, leave it as a timestamp:
    $timestamp_start = $start;
  }
  // Same as above, but make sure $end has actually been overridden with a non-null,
  // non-empty, non-numeric value:
  if (!is_null($end) && (!empty($end) && !is_numeric($end))) {
    $timestamp_end = strtotime($end);
  }
  else {
    // If $end is NULL or empty and non-numeric value, assume the end time desired
    // is the current time (useful for age, etc):
    $timestamp_end = time();
  }
  // Regardless, set the start and end times to an integer:
  $start_time = (int) $timestamp_start;
  $end_time = (int) $timestamp_end;

  // Assign these values as the params for $then and $now:
  $start_time_var = 'start_time';
  $end_time_var = 'end_time';
  // Use this to determine if the output is positive (time passed) or negative (future):
  $pos_neg = 1;

  // If the end time is at a later time than the start time, do the opposite:
  if ($end_time <= $start_time) {
    $start_time_var = 'end_time';
    $end_time_var = 'start_time';
    $pos_neg = -1;
  }

  // Convert everything to the proper format, and do some math:
  $then = new DateTime(date('Y-m-d H:i:s', $$start_time_var));
  $now = new DateTime(date('Y-m-d H:i:s', $$end_time_var));

  $years_then = $then->format('Y');
  $years_now = $now->format('Y');
  $years = $years_now - $years_then;

  $months_then = $then->format('m');
  $months_now = $now->format('m');
  $months = $months_now - $months_then;

  $days_then = $then->format('d');
  $days_now = $now->format('d');
  $days = $days_now - $days_then;

  $hours_then = $then->format('H');
  $hours_now = $now->format('H');
  $hours = $hours_now - $hours_then;

  $minutes_then = $then->format('i');
  $minutes_now = $now->format('i');
  $minutes = $minutes_now - $minutes_then;

  $seconds_then = $then->format('s');
  $seconds_now = $now->format('s');
  $seconds = $seconds_now - $seconds_then;

  if ($seconds < 0) {
    $minutes -= 1;
    $seconds += 60;
  }
  if ($minutes < 0) {
    $hours -= 1;
    $minutes += 60;
  }
  if ($hours < 0) {
    $days -= 1;
    $hours += 24;
  }
  $months_last = $months_now - 1;
  if ($months_now == 1) {
    $years_now -= 1;
    $months_last = 12;
  }

  // "Thirty days hath September, April, June, and November" ;)
  if ($months_last == 9 || $months_last == 4 || $months_last == 6 || $months_last == 11) {
    $days_last_month = 30;
  }
  else if ($months_last == 2) {
    // Factor in leap years:
    if (($years_now % 4) == 0) {
      $days_last_month = 29;
    }
    else {
      $days_last_month = 28;
    }
  }
  else {
    $days_last_month = 31;
  }
  if ($days < 0) {
    $months -= 1;
    $days += $days_last_month;
  }
  if ($months < 0) {
    $years -= 1;
    $months += 12;
  }

  // Finally, multiply each value by either 1 (in which case it will stay the same),
  // or by -1 (in which case it will become negative, for future dates).
  // Note: 0 * 1 == 0 * -1 == 0
  $out = new stdClass;
  $out->years = (int) $years * $pos_neg;
  $out->months = (int) $months * $pos_neg;
  $out->days = (int) $days * $pos_neg;
  $out->hours = (int) $hours * $pos_neg;
  $out->minutes = (int) $minutes * $pos_neg;
  $out->seconds = (int) $seconds * $pos_neg;
  return $out;
}

사용법 예 :

<?php
  $birthday = 'June 2, 1971';
  $check_age_for_this_date = 'June 3, 1999 8:53pm';
  $age = time_diff($birthday, $check_age_for_this_date)->years;
  print $age;// 28

또는:

<?php
  $christmas_2020 = 'December 25, 2020';
  $countdown = time_diff($christmas_2020);
  print_r($countdown);

5

"날짜"가 MySQL에 저장되어 있으면 데이터베이스 수준에서 차이 계산을 수행하는 것이 더 쉽다는 것을 알았습니다 ... 그런 다음 Day, Hour, Min, Sec 출력을 기반으로 결과를 구문 분석하고 표시합니다 ...

mysql> select firstName, convert_tz(loginDate, '+00:00', '-04:00') as loginDate, TIMESTAMPDIFF(DAY, loginDate, now()) as 'Day', TIMESTAMPDIFF(HOUR, loginDate, now())+4 as 'Hour', TIMESTAMPDIFF(MINUTE, loginDate, now())+(60*4) as 'Min', TIMESTAMPDIFF(SECOND, loginDate, now())+(60*60*4) as 'Sec' from User_ where userId != '10158' AND userId != '10198' group by emailAddress order by loginDate desc;
 +-----------+---------------------+------+------+------+--------+
 | firstName | loginDate           | Day  | Hour | Min  | Sec    |
 +-----------+---------------------+------+------+------+--------+
 | Peter     | 2014-03-30 18:54:40 |    0 |    4 |  244 |  14644 |
 | Keith     | 2014-03-30 18:54:11 |    0 |    4 |  244 |  14673 |
 | Andres    | 2014-03-28 09:20:10 |    2 |   61 | 3698 | 221914 |
 | Nadeem    | 2014-03-26 09:33:43 |    4 |  109 | 6565 | 393901 |
 +-----------+---------------------+------+------+------+--------+
 4 rows in set (0.00 sec)

5

다음 페이지에서 기사를 찾았으며 여기에는 PHP 날짜 시간 계산에 대한 많은 참조가 포함되어 있습니다 .

PHP를 사용하여 두 날짜와 시간의 차이를 계산하십시오. 다음 페이지는 PHP를 사용하여 날짜 / 시간 계산을 수행하기위한 다양한 방법 (총 7 개)을 제공하여 두 날짜 사이의 시간 (시간, munite), 일, 월 또는 년의 차이를 결정합니다.

PHP 날짜 시간 – 7 두 날짜의 차이를 계산하는 방법을 참조하십시오 .


4

다음 코드를 사용하여 날짜 차이를 둥근 분수로 반환 할 수도 있습니다. $ date1 = $ duedate; // 마감일 지정 echo $ date2 = date ( "Ymd"); // 현재 날짜 $ ts1 = strtotime ($ date1); $ ts2 = strtotime ($ 날짜 2); $ seconds_diff = $ ts1-$ ts2; 에코 $ datediff = ceil (($ seconds_diff / 3600) / 24); // 일 반환

ceil 대신 php의 floor 메소드를 사용하면 둥근 분수가 반환됩니다. 준비 서버 시간대가 실제 사이트 시간대와 다른 경우 차이를 확인하십시오.이 경우 다른 결과를 얻을 수 있으므로 그에 따라 조건을 변경하십시오.


4
$date1 = date_create('2007-03-24');
$date2 = date_create('2009-06-26');
$interval = date_diff($date1, $date2);
echo "difference : " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days ";

4

년과 월 단위로 나이를 반환 할 수있는 다음 함수를 항상 사용할 수 있습니다 (예 : 1 년 4 개월)

function getAge($dob, $age_at_date)
{  
    $d1 = new DateTime($dob);
    $d2 = new DateTime($age_at_date);
    $age = $d2->diff($d1);
    $years = $age->y;
    $months = $age->m;

    return $years.'.'.months;
}

또는 현재 날짜에 나이를 계산하려면 다음을 사용할 수 있습니다.

function getAge($dob)
{  
    $d1 = new DateTime($dob);
    $d2 = new DateTime(date());
    $age = $d2->diff($d1);
    $years = $age->y;
    $months = $age->m;

    return $years.'.'.months;
}

4

PHP 버전> = 5.3의 경우 : 두 개의 날짜 객체를 만든 다음 date_diff()함수 를 사용하십시오 . PHP DateInterval 객체 를 반환 합니다. 설명서를 참조하십시오

$date1=date_create("2007-03-24");
$date2=date_create("2009-06-26");
$diff=date_diff($date1,$date2);
echo $diff->format("%R%a days");

4

실행 가능한 코드는 다음과 같습니다.

$date1 = date_create('2007-03-24');
$date2 = date_create('2009-06-26');
$diff1 = date_diff($date1,$date2);
$daysdiff = $diff1->format("%R%a");
$daysdiff = abs($daysdiff);

3

PHP 5.2와 같은 문제가 있었고 MySQL로 해결했습니다. 정확히 당신이 찾고있는 것은 아니지만 이것은 트릭을 수행하고 일 수를 반환합니다.

$datediff_q = $dbh->prepare("SELECT DATEDIFF(:date2, :date1)");
$datediff_q->bindValue(':date1', '2007-03-24', PDO::PARAM_STR);
$datediff_q->bindValue(':date2', '2009-06-26', PDO::PARAM_STR);
$datediff = ($datediff_q->execute()) ? $datediff_q->fetchColumn(0) : false;

자세한 정보는 여기 http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_datediff


3

모두가 코드 샘플을 게시하고 있으므로 여기에 다른 버전이 있습니다.

몇 초에서 몇 년 사이의 차이를 표시하는 기능 (단 하나의 장치)을 원했습니다. 1 일이 넘는 기간 동안 자정에 롤오버하기를 원했습니다 (월요일 오전 9 시부 터 월요일 오전 10 시가 1 일이 아니라 2 일 전임). 그리고 한 달이 넘는 기간 동안 롤오버가 해당 월의 같은 날 (30/31 일 개월 및 윤년 포함)에 있기를 원했습니다.

이것이 내가 생각해 낸 것입니다.

/**
 * Returns how long ago something happened in the past, showing it
 * as n seconds / minutes / hours / days / weeks / months / years ago.
 *
 * For periods over a day, it rolls over at midnight (so doesn't depend
 * on current time of day), and it correctly accounts for month-lengths
 * and leap-years (months and years rollover on current day of month).
 *
 * $param string $timestamp in DateTime format
 * $return string description of interval
 */
function ago($timestamp)
{
    $then = date_create($timestamp);

    // for anything over 1 day, make it rollover on midnight
    $today = date_create('tomorrow'); // ie end of today
    $diff = date_diff($then, $today);

    if ($diff->y > 0) return $diff->y.' year'.($diff->y>1?'s':'').' ago';
    if ($diff->m > 0) return $diff->m.' month'.($diff->m>1?'s':'').' ago';
    $diffW = floor($diff->d / 7);
    if ($diffW > 0) return $diffW.' week'.($diffW>1?'s':'').' ago';
    if ($diff->d > 1) return $diff->d.' day'.($diff->d>1?'s':'').' ago';

    // for anything less than 1 day, base it off 'now'
    $now = date_create();
    $diff = date_diff($then, $now);

    if ($diff->d > 0) return 'yesterday';
    if ($diff->h > 0) return $diff->h.' hour'.($diff->h>1?'s':'').' ago';
    if ($diff->i > 0) return $diff->i.' minute'.($diff->i>1?'s':'').' ago';
    return $diff->s.' second'.($diff->s==1?'':'s').' ago';
}

3

얼마 전에 나는 날짜를 원하는 방식에 대한 많은 옵션을format_date 제공하기 때문에 함수를 작성했습니다 .

function format_date($date, $type, $seperator="-")
{
    if($date)
    {
        $day = date("j", strtotime($date));
        $month = date("n", strtotime($date));
        $year = date("Y", strtotime($date));
        $hour = date("H", strtotime($date));
        $min = date("i", strtotime($date));
        $sec = date("s", strtotime($date));

        switch($type)
        {
            case 0:  $date = date("Y".$seperator."m".$seperator."d",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 1:  $date = date("D, F j, Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 2:  $date = date("d".$seperator."m".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 3:  $date = date("d".$seperator."M".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 4:  $date = date("d".$seperator."M".$seperator."Y h:i A",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 5:  $date = date("m".$seperator."d".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 6:  $date = date("M",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 7:  $date = date("Y",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 8:  $date = date("j",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 9:  $date = date("n",mktime($hour, $min, $sec, $month, $day, $year)); break;
            case 10: 
                     $diff = abs(strtotime($date) - strtotime(date("Y-m-d h:i:s"))); 
                     $years = floor($diff / (365*60*60*24));
                     $months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
                     $days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));
                     $date = $years . " years, " . $months . " months, " . $days . "days";
        }
    }
    return($date);
}    

2
이 답변은 khaldonno의 답변만큼이나 잘못되었습니다. 1 년에 365 일 (4 년마다 366 일 (그레고리력의 경우 100 년 / 400 년 규칙 제외)이 있음)이고 한 달에 30 일 (약 30.42 일)이 있다고 가정합니다 (사례 10). 윤년이 아닌 해에). 더 나은 상수를 사용하더라도 평균에 대해서만 정확하며 두 개의 특정 날짜에 반드시 맞지는 않습니다.
Peter Mortensen

3

매우 간단합니다 :

    <?php
        $date1 = date_create("2007-03-24");
        echo "Start date: ".$date1->format("Y-m-d")."<br>";
        $date2 = date_create("2009-06-26");
        echo "End date: ".$date2->format("Y-m-d")."<br>";
        $diff = date_diff($date1,$date2);
        echo "Difference between start date and end date: ".$diff->format("%y years, %m months and %d days")."<br>";
    ?>

자세한 내용은 다음 링크를 확인하십시오.

PHP : date_diff-수동

PHP 5.3.0 이상용입니다.


3

쉬운 기능

function time_difference($time_1, $time_2, $limit = null)
{

    $val_1 = new DateTime($time_1);
    $val_2 = new DateTime($time_2);

    $interval = $val_1->diff($val_2);

    $output = array(
        "year" => $interval->y,
        "month" => $interval->m,
        "day" => $interval->d,
        "hour" => $interval->h,
        "minute" => $interval->i,
        "second" => $interval->s
    );

    $return = "";
    foreach ($output AS $key => $value) {

        if ($value == 1)
            $return .= $value . " " . $key . " ";
        elseif ($value >= 1)
            $return .= $value . " " . $key . "s ";

        if ($key == $limit)
            return trim($return);
    }
    return trim($return);
}

처럼 사용

echo time_difference ($time_1, $time_2, "day");

다음과 같이 반환됩니다 2 years 8 months 2 days


3

date_diff () 사용 하여이 간단한 답변을 시도해보십시오 .

$date1 = date_create("2017-11-27");
$date2 = date_create("2018-12-29");
$diff=date_diff($date1,$date2);
$months = $diff->format("%m months");
$years = $diff->format("%y years");
$days = $diff->format("%d days");

echo $years .' '.$months.' '.$days;

출력은 다음과 같습니다

1 years 1 months 2 days

2

PHP 5.3 (각각 date_diff ())을 사용할 수 없을 때 작성한 다음 함수를 사용하고 있습니다.

        function dateDifference($startDate, $endDate)
        {
            $startDate = strtotime($startDate);
            $endDate = strtotime($endDate);
            if ($startDate === false || $startDate < 0 || $endDate === false || $endDate < 0 || $startDate > $endDate)
                return false;

            $years = date('Y', $endDate) - date('Y', $startDate);

            $endMonth = date('m', $endDate);
            $startMonth = date('m', $startDate);

            // Calculate months
            $months = $endMonth - $startMonth;
            if ($months <= 0)  {
                $months += 12;
                $years--;
            }
            if ($years < 0)
                return false;

            // Calculate the days
            $measure = ($months == 1) ? 'month' : 'months';
            $days = $endDate - strtotime('+' . $months . ' ' . $measure, $startDate);
            $days = date('z', $days);   

            return array($years, $months, $days);
        }

2

DateInterval 훌륭하지만 몇 가지주의 사항이 있습니다.

  1. PHP 5.3 이상에서만 ( 하지만 더 이상 좋은 변명은 아닙니다 )
  2. 년, 월, 일, 시간, 분 및 초만 지원 (주 없음)
  3. 위의 모든 + 일과의 차이를 계산합니다 (몇 달 만 차이를 얻을 수는 없습니다)

이를 극복하기 위해 다음을 코딩했습니다 ( @enobrev answer 개선 ).

function date_dif($since, $until, $keys = 'year|month|week|day|hour|minute|second')
{
    $date = array_map('strtotime', array($since, $until));

    if ((count($date = array_filter($date, 'is_int')) == 2) && (sort($date) === true))
    {
        $result = array_fill_keys(explode('|', $keys), 0);

        foreach (preg_grep('~^(?:year|month)~i', $result) as $key => $value)
        {
            while ($date[1] >= strtotime(sprintf('+%u %s', $value + 1, $key), $date[0]))
            {
                ++$value;
            }

            $date[0] = strtotime(sprintf('+%u %s', $result[$key] = $value, $key), $date[0]);
        }

        foreach (preg_grep('~^(?:year|month)~i', $result, PREG_GREP_INVERT) as $key => $value)
        {
            if (($value = intval(abs($date[0] - $date[1]) / strtotime(sprintf('%u %s', 1, $key), 0))) > 0)
            {
                $date[0] = strtotime(sprintf('+%u %s', $result[$key] = $value, $key), $date[0]);
            }
        }

        return $result;
    }

    return false;
}

두 개의 루프를 실행합니다. 첫 번째는 무차별 강제를 통해 상대 간격 (년 및 월)을 처리하고 두 번째는 간단한 산술로 추가 절대 간격을 계산하므로 더 빠릅니다.

echo humanize(date_dif('2007-03-24', '2009-07-31', 'second')); // 74300400 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'minute|second')); // 1238400 minutes, 0 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'hour|minute|second')); // 20640 hours, 0 minutes, 0 seconds
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|day')); // 2 years, 129 days
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|week')); // 2 years, 18 weeks
echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|week|day')); // 2 years, 18 weeks, 3 days
echo humanize(date_dif('2007-03-24', '2009-07-31')); // 2 years, 4 months, 1 week, 0 days, 0 hours, 0 minutes, 0 seconds

function humanize($array)
{
    $result = array();

    foreach ($array as $key => $value)
    {
        $result[$key] = $value . ' ' . $key;

        if ($value != 1)
        {
            $result[$key] .= 's';
        }
    }

    return implode(', ', $result);
}

@ PeterMortensen : 작동해야하지만 보장하지는 않습니다. 시간대를 설정하고 이동하십시오.
Alix Axel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.