Класс DatePeriod

(PHP 5 >= 5.3.0)

Введение

Представляет временной период.

Позволяет перемещаться в заданном временном интервале на равные промежутки времени.

Обзор классов

DatePeriod implements Traversable {
/* Константы */
const integer EXCLUDE_START_DATE = 1 ;
/* Методы */
public __construct ( DateTime $start , DateInterval $interval , int $recurrences [, int $options ] )
public __construct ( DateTime $start , DateInterval $interval , DateTime $end [, int $options ] )
public __construct ( string $isostr [, int $options ] )
}

Предопределенные константы

DatePeriod::EXCLUDE_START_DATE

Исключает начальную дату, используется в DatePeriod::__construct().

Содержание

Коментарии

Nice example from PHP Spring Conference (thanks to Johannes Schlüter and David Zülke)

<?php
$begin 
= new DateTime'2007-12-31' );
$end = new DateTime'2009-12-31 23:59:59' );

$interval DateInterval::createFromDateString('last thursday of next month');
$period = new DatePeriod($begin$interval$endDatePeriod::EXCLUDE_START_DATE);

foreach ( 
$period as $dt )
  echo 
$dt->format"l Y-m-d H:i:s\n" );
?>

DateInterval specs could be found at http://en.wikipedia.org/wiki/ISO_8601#Time_intervals
2009-07-10 04:55:28
http://php5.kiev.ua/manual/ru/class.dateperiod.html
Автор:
If you want to include the end-date, add one day to it:

<?php
$startDate 
= new DateTime();
$endDate = new DateTime();

$startDateInt = new DateInterval"P1Y" );
$endDateInt = new DateInterval"P1D" );

$startDate->sub$startDateInt );
$endDate->add$endDateInt );

$periodInt = new DateInterval"P1M" );
$period = new DatePeriod$startDate$periodInt$endDate );

// At februari 2011:
// $period = (8,9,10,11,12,1,2)
?>
2011-02-25 02:19:58
http://php5.kiev.ua/manual/ru/class.dateperiod.html
Thanks much to those of you who supplied sample code; that helps a lot.

I wanted to mention another thing that helped me: when you do that foreach ( $period as $dt ), the $dt values are DateTime objects.

That may be obvious to those of you with more experience, but I wasn't sure until I looked it up on Stack Overflow. So I figured it was worth posting here to help others like me who might've been confused or uncertain.
2012-07-05 22:18:36
http://php5.kiev.ua/manual/ru/class.dateperiod.html
Just an example to include the end date using the DateTime method 'modify'

<?php

$begin 
= new DateTime'2012-08-01' );
$end = new DateTime'2012-08-31' );
$end $end->modify'+1 day' ); 

$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin$interval ,$end);

foreach(
$daterange as $date){
    echo 
$date->format("Ymd") . "<br>";
}
?>
2012-08-27 17:23:10
http://php5.kiev.ua/manual/ru/class.dateperiod.html
DatePeriod is not compatible with negative intervals.

To do so you can simply use DateInterval and loop through it yourself like this: (not start should be ahead of end if you use a negative interval

    class DateRange extends ArrayIterator
    {

        protected $oDate = null;
        protected $oStartDate = null;
        protected $oEndDate = null;
        protected $oInterval = null;

        public function __construct( DateTime $oStartDate, DateTime $oEndDate, DateInterval $oInterval = null )
        {
            $this->oStartDate = $oStartDate;
            $this->oDate = clone $oStartDate;
            $this->oEndDate = $oEndDate;
            $this->oInterval = $oInterval;
        }

        public function next()
        {
            $this->oDate->add($this->oInterval);
            return $this->oDate;
        }

        public function current()
        {
            return $this->oDate;
        }

        public function valid()
        {
            if ($this->oStartDate > $this->oEndDate)
            {
                return $this->oDate >= $this->oEndDate;
            }
            return $this->oDate <= $this->oEndDate;
        }

    }

$oRange = new DateRange(new DateTime("2013-10-01"), new DateTime("2013-01-01"), DateInterval::createFromDateString("-1 month") );
    foreach ($oRange as $oDate)
    {
        echo $oDate->format("Y-m-d") . "<br />";
    }
2014-01-22 13:32:06
http://php5.kiev.ua/manual/ru/class.dateperiod.html
The iterator seems to check the time as well, it excludes the end element if its time is 00:00:00. So the slightly safer version (to compare it against joshs suggestion) is to use $date->setTime(23, 59, 59) instead of $date->modify("+1 day").
2015-06-22 15:34:11
http://php5.kiev.ua/manual/ru/class.dateperiod.html
When looping over a DatePeriod object, the returned objects always implement DateTimeInterface. The exact type returned depends on how the DatePeriod was created. If $start was a DateTimeImmutable, the objects returned will be of type DateTimeImmutable. If a DateTime object was used, the objects returned will be of type DateTime.
2017-01-19 11:58:04
http://php5.kiev.ua/manual/ru/class.dateperiod.html
Calculating business days can be cumbersome. Here is an iterator for handling business days. Usage examples below for adding # of business days and calculating how many business days between two dates.

Here is the iterator class
https://gist.github.com/styks1987/29dd0f6a68e3b07ba70fec18f732eb86

Usage

Counting # of Business Days between two dates

<?php
function countBusinessDays($start$stop)
    {
        if(
$start $stop){
           
$tmpStart = clone $start;
           
$start = clone $stop;
           
$stop = clone $tmpStart;
        }

       
// Adding the time to the end date will include it
       
$period = new DatePeriod($start->setTime(0,0,0), new DateInterval('P1D'), $stop->setTime(23,59,59), DatePeriod::EXCLUDE_START_DATE);
       
$periodIterator = new BusinessDayPeriodIterator($period);
       
$businessDays 0;
        while(
$periodIterator->valid()){
           
// If we run into a weekend, don't count it
           
if(!$periodIterator->isWeekend()){
               
$businessDays++;
            }
           
$periodIterator->next();
        }

        return 
$businessDays;
    }
?>

Add # of business days

<?php
function addBusinessDays(DateTime $startDateTime$daysToAdd)
    {
       
$endDateTime = clone $startDateTime;
       
$endDateTime->add(new DateInterval('P' $daysToAdd 'D'))->setTime(23,59,59);
       
$period = new DatePeriod($startDateTime, new DateInterval('P1D'), $endDateTime);

       
$periodIterator = new BusinessDayPeriodIterator($period);
       
$adjustedEndingDate = clone $startDateTime;
        while(
$periodIterator->valid()){
           
$adjustedEndingDate $periodIterator->current();
           
// If we run into a weekend, extend our days
           
if($periodIterator->isWeekend()){
               
$periodIterator->extend();
            }
           
$periodIterator->next();
        }

        return 
$adjustedEndingDate;
    }
?>
2017-05-11 19:06:09
http://php5.kiev.ua/manual/ru/class.dateperiod.html
As someone noted, at least in 7.2, dates with time 0 are excluded from the start and end. 

To get a regular span of dates I ended up with:

$dates = new DatePeriod(
    ( new DateTime($date_start) )->setTime(0,0,1),
    new DateInterval('P1D'),
    ( new DateTime($date_end) )->setTime(0,0,1)
);
2018-04-26 16:27:05
http://php5.kiev.ua/manual/ru/class.dateperiod.html
An extra piece of information on how to use the (modify method) to easily get date ranges:

<?php
$subscription_start_date 
= new DateTime'now' );

// Modify the $subscription_start_date date value to required date range, 
// this could be in days or months depending on how your application is designed

// Days
$subscription_expiration $subscription_start_date->modify'+60 days' ); 
echo 
$subscription_expiration->format'Y-m-d' ) . "\n";

// Months
$subscription_expiration $subscription_start_date->modify'+2 Months' );
echo 
$subscription_expiration->format'Y-m-d' ) . "\n";

// Or even in years
$subscription_expiration $subscription_start_date->modify'+2 years' );
echo 
$subscription_expiration->format'Y-m-d' ) . "\n";
?>
2018-11-29 22:19:06
http://php5.kiev.ua/manual/ru/class.dateperiod.html
Автор:
This class isn't always intuitive. End is exclusive. All you need to do to include it is to add a second (the smallest amount).

Microseconds are ignored.

php -r '
/***/$p1d = new DateInterval("P1D");
/***/$b = (new DateTime())->setTime(0, 0, 0, 0);
/***/$a = (clone $b)->sub($p1d);

/***/$f = function(DateTime $b)use($a, $p1d):void {
/***//***/$p = new DatePeriod($a, $p1d, $b);
/***//***/$i = iterator_to_array($p);
/***//***/print_r([$i[0], end($i), $a, $b]);
/***/};

/***/$f($b);
/***/$f($b->setTime(0, 0, 0, 1));
/***/$f($b->setTime(0, 0, 1, 0));
'

It is a sign of the end times.
2019-08-27 18:11:36
http://php5.kiev.ua/manual/ru/class.dateperiod.html

    Поддержать сайт на родительском проекте КГБ