你如何实际执行日期时间的操作,如加入的日期,发现差异,找出多少天不包括周末在一个间隔时间?我个人开始通过这些行动对我postgresql dbms为通常我只需要问题之一sql statement得到一个答案,但是,要做到这PHP方式,我将必须编写更多的代码这意味着更多的机会针对发生错误...

是否有任何库PHP不datetime操作方式不需要大量的代码?拍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+'s 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::加 (增加量的几天、几个月、数年时、分和秒DateTime对象),可从php5.3.0开始。

找到两个日期之间的差值,有的 DateTime::差 方法;但是那里似乎并不是一个方法,用于计算工作日之间,两个日期。

PEAR::Date 看起来像它可能有一些有用功能。

PEAR::Calendar 也可能是有用的。

最简单的方法是使用时间戳,以表示该数秒钟,因为月1日,2008年。时间戳类型,你可以做的事情像是...

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

检查了文档 时间(), date()mktime() 在php的网页。这些都是三种方法,我倾向于使用最频繁。

你可以使用一个组合 strtotime, mktime日期 todo的算术

这里是一个例子,它使用一个组合todo一些算法 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";
}
?>

@是我不喜欢strtotime()个人..我不知道为什么但是我发现今天上午通过一串这样的'2008-09-11 9:5AM'到strtotime返回一个虚假的...

我不认为你的代码提供了解决的例子的问题'指定两个日期,有多少个工作日之间有两个日期?实现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);

我强烈建议使用PHP5.2的 DateTime对象, ,而不是使用UNIX时间戳,以时日计算。当你使用PHP日期功能返回UNIX timestamps,你有一个非常有限的范围内的工作(例如什么之前,1970年)。

如果你看一看 http://php.net/date 你会发现一些实例的使用 mktime() 执行操作。

一个简单的例子就是锻炼什么样的明天的日期。你可以做的是,通过简单地增加1,到一天的价值 mktime() 如下:

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

因此,在这里,你会收到一种新形式的YYYY-MM-DD含有明天的日期。你也可以减天通过简单地取代'+'with'-'. mktime() 使得生活变得更容易,并节省了你做套如果报表和其他这样的麻烦的编码。

获得工作日和节假日,postgresql CTE融通--见 http://osssmb.wordpress.com/2009/12/02/business-days-working-days-sql-for-postgres-2/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top