您实际上如何执行日期时间操作,例如添加日期,查找差异,找出间隔中不包括周末的多少天?我个人开始将这些操作中的一些传递给我的postgresql dbms,因为通常我只需要发出一个sql语句来获得答案,但是,以PHP的方式进行操作,我将不得不编写更多的代码,这意味着更多的机会发生错误…
PHP中是否有任何不需要大量代码即可进行日期时间操作的库?在“给定两个日期,两个日期之间有多少个工作日?以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对象很有用,因为它知道leap时间和夏令时,但是它需要一些扩展才能真正解决问题。我写了下面的文章来解决类似的问题。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