DatePeriod::__construct

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

DatePeriod::__constructCreates a new DatePeriod object

Description

public DatePeriod::__construct(
    DateTimeInterface $start,
    DateInterval $interval,
    int $recurrences,
    int $options = 0
)
public DatePeriod::__construct(
    DateTimeInterface $start,
    DateInterval $interval,
    DateTimeInterface $end,
    int $options = 0
)
Warning
public DatePeriod::__construct(string $isostr, int $options = 0)

This variant of the constructor has been deprecated, use DatePeriod::createFromISO8601String() instead.

Creates a new DatePeriod object.

DatePeriod objects can be used as an iterator to generate a number of DateTimeImmutable or DateTime object from a start date, a interval, and an end date or the number of recurrences.

The class of returned objects is equivalent to the DateTimeImmutable or DateTime ancestor class of the start object.

Parameters

start

The start date of the period. Included by default in the result set.

interval

The interval between recurrences within the period.

recurrences

The number of recurrences. The number of returned results is one higher than this, as the start date is included in the result set by default. Must be greater than 0.

end

The end date of the period. Excluded by default from the result set.

isostr

A subset of the » ISO 8601 repeating interval specification.

Examples of some ISO 8601 interval specification features that PHP does not support are:

  1. zero occurrences (R0/)
  2. time offsets other than UTC (Z), such as +02:00.
options

A bit field which can be used to control certain behaviour with start- and end- dates.

With DatePeriod::EXCLUDE_START_DATE you exclude the start date from the set of recurring dates within the period.

With DatePeriod::INCLUDE_END_DATE you include the end date in the set of recurring dates within the period.

Errors/Exceptions

Throws an DateMalformedPeriodStringException when the isostr cannot be parsed as a valid ISO 8601 period. Prior to PHP 8.3, this was Exception.

Changelog

Version Description
8.3.0 Now throws DateMalformedPeriodStringException instead of Exception.
8.2.0 The DatePeriod::INCLUDE_END_DATE constant has been added.
7.2.19, 7.3.6, 7.4.0 recurrences must be greater than 0 now.

Examples

Example #1 DatePeriod example

<?php
$start
= new DateTime('2012-07-01');
$interval = new DateInterval('P7D');
$end = new DateTime('2012-07-31');
$recurrences = 4;
$iso = 'R4/2012-07-01T00:00:00Z/P7D';

// All of these periods are equivalent.
$period = new DatePeriod($start, $interval, $recurrences);
$period = new DatePeriod($start, $interval, $end);
$period = new DatePeriod($iso);

// By iterating over the DatePeriod object, all of the
// recurring dates within that period are printed.
foreach ($period as $date) {
echo
$date->format('Y-m-d')."\n";
}
?>

The above example will output:

2012-07-01
2012-07-08
2012-07-15
2012-07-22
2012-07-29

Example #2 DatePeriod example with DatePeriod::EXCLUDE_START_DATE

<?php
$start
= new DateTime('2012-07-01');
$interval = new DateInterval('P7D');
$end = new DateTime('2012-07-31');

$period = new DatePeriod($start, $interval, $end,
DatePeriod::EXCLUDE_START_DATE);

// By iterating over the DatePeriod object, all of the
// recurring dates within that period are printed.
// Note that, in this case, 2012-07-01 is not printed.
foreach ($period as $date) {
echo
$date->format('Y-m-d')."\n";
}
?>

The above example will output:

2012-07-08
2012-07-15
2012-07-22
2012-07-29

Example #3 DatePeriod example showing all last Thursdays in a year

<?php
$begin
= new DateTime('2021-12-31');
$end = new DateTime('2022-12-31 23:59:59');

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

foreach (
$period as $dt) {
echo
$dt->format('l Y-m-d'), "\n";
}
?>

The above example will output:

Thursday 2022-01-27
Thursday 2022-02-24
Thursday 2022-03-31
Thursday 2022-04-28
Thursday 2022-05-26
Thursday 2022-06-30
Thursday 2022-07-28
Thursday 2022-08-25
Thursday 2022-09-29
Thursday 2022-10-27
Thursday 2022-11-24
Thursday 2022-12-29

Notes

Unbound numbers of repetitions as specified by ISO 8601 section 4.5 "Recurring time interval" are not supported, i.e. neither passing "R/..." as isostr nor passing null as end would work.

add a note add a note

User Contributed Notes 4 notes

up
36
simon dot kohlmeyer at mayflower dot de
14 years ago
I found two things useful to know that aren't covered here.

1. endDate is excluded:

<?php
$i
= new DateInterval('P1D');
$d1 = new Datetime();
$d2 = clone $d1; $d2->add($i);
foreach(new
DatePeriod($d1, $i, $d2) as $d) {
    echo
$d->format('Y-m-d H:i:s') . "\n";
}
?>

Will output:
2010-11-03 12:39:53

(Another one because I got it wrong at first)
2. For the first form, recurrences really means REcurrences, not occurences.

<?php
$i
= new DateInterval('P1D');
$d = new Datetime();
foreach(new
DatePeriod($d, $i, 1) as $d) {
    echo
$d->format('Y-m-d H:i:s') . "\n";
}
?>

Will output:
2010-11-03 12:41:05
2010-11-04 12:41:05
up
14
lars at hp-designs dot com
12 years ago
When you add the time 23:59:59 to the end DateTime object something like the following then the end date will be included in the period:

<?php
$date_start
= new DateTime('2012-03-12');
$date_end = new DateTime('2012-03-22 23:59:59');

$interval = '+2 days';
$date_interval = DateInterval::createFromDateString($interval);

$period = new DatePeriod($date_start, $date_interval, $date_end, DatePeriod::EXCLUDE_START_DATE);

foreach(
$period as $dt) {
echo
$dt->format('d/m');
}
?>

OUTPUT:
14/03
16/03
18/03
20/03
22/03
up
0
bill at bwi dot com
3 years ago
With reference to the Changelog above, 'recurrences' must be greater than 0 now.

This was not the case in PHP5 ( >= 5.3.0). A foreach loop over a DatePeriod with recurrences == 0 would
execute one time. A function could accept a $count parameter which represented the number of times to execute
the code in a foreach loop, and then initialize a DatePeriod with 'recurrences' == ($count-1) to get the desired
number of iterations.

The following example adds a special case for PHP7 and above to handle the situation where a single
iteration is desired.

Note that an alternative solution to subracting 1 from the desired count is to subtract one month from the desired starting month,      
and then intialize the DatePeriod with the option DatePeriod::EXCLUDE_START_DATE.

<?php
       
// displayCalender() is a stub.
        // In a real application, this would generate a displayable calendar for the specified month.
        //
        // $tp is a DateTime object used to specify the month for which a calendar will be displayed
       
function displayCalendar($tp)
        {
               
$format = "F, Y";
                echo
"Display Calendar for " . $tp->format($format) . "\n";
        }

       
// $date is the first month to show
        // $count is the number of months to show
        // NOTE: the number of "recurrences" is one less than the number of months to display
       
function showMonths($date = false, $count = 1)
        {
               
$format = "Y-m-d 00:00:00";
               
$init = ($date ? $date : date($format));
               
$one_month = new DateInterval("P1M");

               
// get the starting month and day
               
$start = new DateTime($init);

                echo
"Show $count month" . ($count > 1 ? "s" : "") . "\n";
               
//check for PHP7 or greater
               
if ($count == 1 && (substr(phpversion(), 0, 1) >= 7) )
                {
                       
// Special case for PHP7 when $count == 1
                       
displayCalendar($start);
                }  
                else
                {
                       
// PHP5 does not need special case, because 0 is accepted value
                        //      for number of recurrences
                       
$time_period = new DatePeriod($start, $one_month, ($count-1));
                        foreach (
$time_period as $tp)
                        {
                               
displayCalendar($tp);
                        }
                }
                echo
"\n";
        }
       
       
// Show calendar for specific month
       
$first_month = "2021-11";
       
showMonths($first_month);
       
       
// Show calendars for a full year
       
$first_month = "2021-01";
       
showMonths($first_month, 12);
?>

The above example will output:

Show 1 month
Display Calendar for November, 2021

Show 12 months
Display Calendar for January, 2021
Display Calendar for February, 2021
Display Calendar for March, 2021
Display Calendar for April, 2021
Display Calendar for May, 2021
Display Calendar for June, 2021
Display Calendar for July, 2021
Display Calendar for August, 2021
Display Calendar for September, 2021
Display Calendar for October, 2021
Display Calendar for November, 2021
Display Calendar for December, 2021
up
0
youssef dot benhssaien at gmail dot com
4 years ago
The parameter isostr should accept an ISO 8601 format, but doing this is not work :
<?php
      $dateStart
= date_create('first day of next month this year');

     
$isoStr = $dateStart ->format(DateTimeInterface::ISO8601);
     
$datePeriod = new DatePeriod("R10/{$isoStr}/P1M");
    
// Throw Exception : DatePeriod::__construct(): Unknown or bad format (R10/2020-02-01T22:52:26+0000Z/P1M)
    
     // While doing it by this way works
   
$datePeriod = new DatePeriod($dateStart , \DateInterval::createFromDateString("+1 month"), 10);
?>
To Top