代码之家  ›  专栏  ›  技术社区  ›  Jeffrey04 George

在PHP中执行与日期时间相关的操作

  •  7
  • Jeffrey04 George  · 技术社区  · 17 年前

    您如何实际执行日期时间操作,例如添加日期、查找差异、找出间隔中不包括周末的天数?我个人开始将其中的一些操作传递给我的postgresql dbms,因为通常我只需要发出一条sql语句就可以得到答案,但是,要用PHP的方式进行,我必须编写更多的代码,这意味着发生错误的机会更大。。。

    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;
    
    12 回复  |  直到 12 年前
        1
  •  5
  •   reefnet_alex    17 年前

    对于大多数datetime操作,我通常会转换为Unixtime并对Unixtime整数执行加减等操作,但您可能需要查看Zend framework Zend_Date类。

    这有很多您描述的功能。尽管Zend被宣传为一个“框架”,但它作为一个可以从中挑选元素的类库工作得非常好。我们通常将其包含在项目中,然后在需要的时候将其提取出来。

        2
  •  2
  •   Laith    17 年前

    像“+1个月”或“-3天”这样的东西有时无法提供您期望的输出。

        3
  •  2
  •   Vince Bowdren    16 年前

    要添加日期,可以使用以下方法 日期时间::添加 ( 向DateTime对象添加日、月、年、小时、分钟和秒的数量 ),从PHP5.3.0开始提供。

    要找出两个日期之间的差异,有 DateTime::diff

        4
  •  2
  •   Manoj Sharma    9 年前

    PHP5+的DateTime对象很有用,因为它是闰时和 夏令时意识到,但它需要一些扩展来真正实现 解决问题。我写了以下内容来解决类似的问题。

    $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
    
        5
  •  2
  •   MarredCheese Lionia Vasilev    6 年前

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

    PEAR::Calendar 也可能有用。

        6
  •  1
  •   Jarrett Meyer    17 年前

    最简单的方法是使用时间戳,表示自2008年1月1日以来的秒数。使用时间戳类型,您可以执行以下操作。。。

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

    查看文档以了解更多信息 time() , date() mktime()

        7
  •  0
  •   Rushi    17 年前

    您可以使用以下选项的组合: strtotime , mktime date 做算术题

    下面是一个使用组合来进行一些运算的示例 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";
    }
    ?>
    
        8
  •  0
  •   Jeffrey04 George    17 年前

    @如石我个人不喜欢strotime。。我不知道为什么,但我今天早上发现,将这样的字符串“2008-09-11 9:5 AM”传递给strottime会返回一个错误的。。。

    我认为您提供的代码不能解决示例问题“给定两个日期,两个日期之间有多少个工作日?”?在SQL或$PETLLAN中实现,我没有考虑是否有公共假日列表…

        9
  •  0
  •   Jonathan Sampson    17 年前

    您可以获得两个日期之间的天数,如下所示:

    $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;
    }
    

    如果您不喜欢strotime,并且您总是使用相同格式的日期,您可以使用explode函数,如

    list($year, $month, day) = explode("-", $date);
    
        10
  •  0
  •   JW.    17 年前

    我强烈建议使用PHP5.2 DateTime objects ,而不是在进行日期计算时使用UNIX时间戳。当您使用返回UNIX时间戳的PHP日期函数时,可以使用的范围非常有限(例如,1970年以前没有)。

        11
  •  0
  •   A J    10 年前

    如果你看一看 http://php.net/date ,您将找到一些使用 mktime() 执行操作。

    mktime() 详情如下:

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

    mktime() 使生活变得更加轻松,并使您不必执行嵌套的if语句和其他此类麻烦的编码。

        12
  •  -1
  •   helmi03    14 年前