문제

날짜 추가, 차이 찾기, 간격에서 주말을 제외한 일수 확인과 같은 날짜/시간 작업을 실제로 어떻게 수행합니까?저는 개인적으로 이러한 작업 중 일부를 postgresql dbms에 전달하기 시작했습니다. 일반적으로 답변을 얻으려면 SQL 문 하나만 실행하면 되지만, PHP 방식으로 수행하려면 더 많은 기회를 의미하는 훨씬 더 많은 코드를 작성해야 하기 때문입니다. 오류가 발생하려면...

많은 코드가 필요하지 않은 방식으로 날짜/시간 작업을 수행하는 라이브러리가 PHP에 있습니까?이는 '두 개의 날짜가 주어지면 두 날짜 사이에 몇 일의 근무일이 있습니까?'라는 상황에서 SQL을 능가합니다.이 쿼리를 작성하여 해결된 SQL 또는 $pet_lang'으로 구현하시겠습니까?

SELECT  COUNT(*) AS total_days
FROM    (SELECT date '2008-8-26' + generate_series(0,
          (date '2008-9-1' - date '2008-8-26')) AS all_days) AS calendar
WHERE   EXTRACT(isodow FROM all_days) < 6;
도움이 되었습니까?

해결책

PHP5+의 DateTime 객체는 도약 시간과 일광 절약 인식이기 때문에 유용하지만 실제로 문제를 해결하려면 약간의 확장이 필요합니다.비슷한 문제를 해결하기 위해 다음과 같이 썼습니다.find_WeekdaysFromThisTo() 메서드는 무차별 공격이지만 기간이 2년 미만인 경우 합리적으로 빠르게 작동합니다.

$tryme = new Extended_DateTime('2007-8-26');
$newer = new Extended_DateTime('2008-9-1');

print 'Weekdays From '.$tryme->format('Y-m-d').' To '.$newer->format('Y-m-d').': '.$tryme -> find_WeekdaysFromThisTo($newer) ."\n";
/*  Output:  Weekdays From 2007-08-26 To 2008-09-01: 265  */
print 'All Days From '.$tryme->format('Y-m-d').' To '.$newer->format('Y-m-d').': '.$tryme -> find_AllDaysFromThisTo($newer) ."\n";
/*  Output:  All Days From 2007-08-26 To 2008-09-01: 371   */
$timefrom = $tryme->find_TimeFromThisTo($newer);
print 'Between '.$tryme->format('Y-m-d').' and '.$newer->format('Y-m-d').' there are '.
      $timefrom['years'].' years, '.$timefrom['months'].' months, and '.$timefrom['days'].
      ' days.'."\n";
/*  Output: Between 2007-08-26 and 2008-09-01 there are 1 years, 0 months, and 5 days. */

class Extended_DateTime extends DateTime {

    public function find_TimeFromThisTo($newer) {
        $timefrom = array('years'=>0,'months'=>0,'days'=>0);

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;

        $timefrom['years'] = $this->find_YearsFromThisTo($testnewer);
        $mod = '-'.$timefrom['years'].' years';
        $testnewer -> modify($mod);

        $timefrom['months'] = $this->find_MonthsFromThisTo($testnewer);
        $mod = '-'.$timefrom['months'].' months';
        $testnewer -> modify($mod);

        $timefrom['days'] = $this->find_AllDaysFromThisTo($testnewer);
        return $timefrom;
    } // end function find_TimeFromThisTo


    public function find_YearsFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;
        $count = 0;

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;

        $testnewer -> modify ('-1 year');
        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 year');
        }
        return $count;
    } // end function find_YearsFromThisTo


    public function find_MonthsFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;
        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 month');

        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 month');
        }
        return $count;
    } // end function find_MonthsFromThisTo


    public function find_AllDaysFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;
        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 day');

        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 day');
        }
        return $count;
    } // end function find_AllDaysFromThisTo


    public function find_WeekdaysFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 day');

        while ( $this->format('U') < $testnewer->format('U')) {
            // If the calculated day is not Sunday or Saturday, count this day
            if ($testnewer->format('w') != '0' && $testnewer->format('w') != '6')
                $count ++;
            $testnewer -> modify ('-1 day');
        }
        return $count;
    } // end function find_WeekdaysFromThisTo

    public function set_Day($newday) {
        if (is_int($newday) && $newday > 0 && $newday < 32 && checkdate($this->format('m'),$newday,$this->format('Y')))
            $this->setDate($this->format('Y'),$this->format('m'),$newday);
    } // end function set_Day


    public function set_Month($newmonth) {
        if (is_int($newmonth) && $newmonth > 0 && $newmonth < 13)
            $this->setDate($this->format('Y'),$newmonth,$this->format('d'));
    } // end function set_Month


    public function set_Year($newyear) {
        if (is_int($newyear) && $newyear > 0)
            $this->setDate($newyear,$this->format('m'),$this->format('d'));
    } // end function set_Year
} // end class Extended_DateTime

다른 팁

대부분의 날짜/시간 작업에서는 일반적으로 Unixtime으로 변환하고 덧셈 뺄셈 등을 수행합니다.Unixtime 정수에 대해서는 Zend 프레임워크 Zend_Date 클래스를 살펴보는 것이 좋습니다.

이것은 당신이 설명하는 많은 기능을 가지고 있습니다.Zend는 "프레임워크"로 청구되지만 요소를 선택하고 선택할 수 있는 클래스 라이브러리로서 매우 잘 작동합니다.우리는 정기적으로 프로젝트에 이를 포함시킨 다음 필요할 때마다 조금씩 가져옵니다.

strtotime()은 유용하지만 형식이 지정된 날짜/시간 문자열을 변환하는 데 사용하지 않는 경우 때때로 팝업될 수 있는 몇 가지 이상한 동작이 있습니다.

"+1개월" 또는 "-3일"과 같은 항목은 때때로 예상한 결과를 제공하지 못할 수 있습니다.

날짜를 추가하려면 다음 메소드를 사용할 수 있습니다. 날짜시간::추가 (DateTime 객체에 일, 월, 연, 시, 분, 초를 추가합니다.), PHP 5.3.0부터 사용할 수 있습니다.

두 날짜의 차이를 찾으려면 날짜시간::diff 방법;하지만 두 날짜 사이의 근무일을 계산하는 방법은 없는 것 같습니다.

PEAR::Date 뭔가 유용한 기능이 있을 것 같습니다.

PEAR::Calendar 유용할 수도 있습니다.

가장 쉬운 방법은 2008년 1월 1일 이후의 초 수를 나타내는 타임스탬프를 사용하는 것입니다.타임스탬프 유형을 사용하면 다음과 같은 작업을 수행할 수 있습니다.

now = time();
tomorrow = now + 24 * 60 * 60; // 24 hours * 60 minutes * 60 seconds

다음에 대한 설명서를 확인하세요. 시간(), 날짜() 그리고 MK타임() PHP 웹 페이지에서.제가 자주 사용하는 세 가지 방법입니다.

다음의 조합을 사용할 수 있습니다. strtotime, mktime 그리고 날짜 연산을 해라

다음은 콤보를 사용하여 일부 산술을 수행하는 예입니다. http://rushi.wordpress.com/2008/04/13/php-print-out-age-of-date-in-words/ 단순화를 위해 여기에 코드를 재현하겠습니다.

if ($timestamp_diff < (60*60*24*7)) {
   echo floor($timestamp_diff/60/60/24)." Days";
} elseif ($timestamp_diff > (60*60*24*7*4)) {
   echo floor($timestamp_diff/60/60/24/7)." Weeks";
} else {
   $total_months = $months = floor($timestamp_diff/60/60/24/30);
   if($months >= 12) {
      $months = ($total_months % 12);
      $years&nbsp; = ($total_months - $months)/12;
      echo $years . " Years ";
   }
   if($months > 0)
      echo $months . " Months";
}
?>

@Rushi 저는 개인적으로 strtotime()을 좋아하지 않습니다..이유는 모르겠지만 오늘 아침에 '2008-09-11 9:5 AM'과 같은 문자열을 strtotime에 전달하면 false가 반환된다는 사실을 발견했습니다.

귀하가 제공한 코드가 '두 날짜가 주어지면 두 날짜 사이에 근무일 수는 몇 일입니까?'라는 예제 문제를 해결하지 못하는 것 같습니다.SQL 또는 $pet_lang'으로 구현했는데 공휴일 목록이 있는지 고려하지 않았습니다...

다음과 같이 두 날짜 사이의 일수를 얻을 수 있습니다.

$days = (strtotime("2008-09-10") - strtotime("2008-09-12")) / (60 * 60 * 24);

그리고 다음과 같은 기능을 만들 수 있습니다. (작업 컴퓨터에 PHP가 설치되어 있지 않아 구문이 100% 정확하다고 보장할 수 없습니다.)

function isWorkDay($date)
{
 // check if workday and return true if so
}

function numberOfWorkDays($startdate, $enddate)
{
  $workdays = 0;
  $tmp = strtotime($startdate);
  $end = strtotime($enddate);
  while($tmp <= $end)
  {
    if ( isWorkDay( date("Y-m-d",$tmp) ) ) $workdays++;
    $tmp += 60*60*24;
  }
  return $workdays;
}

strtotime이 마음에 들지 않고 항상 동일한 형식의 날짜가 있는 경우 다음과 같은 분해 기능을 사용할 수 있습니다.

list($year, $month, day) = explode("-", $date);

PHP 5.2를 사용하는 것이 좋습니다. 날짜/시간 객체, 날짜 계산을 수행할 때 UNIX 타임스탬프를 사용하는 대신.UNIX 타임스탬프를 반환하는 PHP 날짜 함수를 사용하면 작업 범위가 매우 제한됩니다(예:1970년 이전에는 아무것도 없었습니다.)

당신이 살펴 본다면 http://php.net/날짜 , 당신은 사용의 몇 가지 예를 찾을 수 있습니다 mktime() 작업을 수행합니다.

간단한 예는 내일 날짜가 언제인지 운동하는 것입니다.간단히 말해서 날짜 값에 1을 더하면 됩니다. mktime() 다음과 같이:

$tomorrow = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")));

따라서 여기서는 내일 날짜를 포함하는 YYYY-MM-DD 형식의 날짜를 받게 됩니다.간단히 '+'를 '-'로 바꿔서 날짜를 뺄 수도 있습니다. mktime() 삶을 훨씬 쉽게 만들고 중첩된 if 문 및 기타 번거로운 코딩을 수행하지 않아도 됩니다.

근무일/휴일을 얻으려면 postgresql CTE ftw -- 참조 http://osssmb.wordpress.com/2009/12/02/business-days-working-days-sql-for-postgres-2/

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top