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";print 'All Days From '.$tryme->format('Y-m-d').' To '.$newer->format('Y-m-d').': '.$tryme -> find_AllDaysFromThisTo($newer) ."n";$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";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 (!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 (!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 (!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 (!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


