25

I understand how date period works with one exception, is there a way to find out from date period how many intervals there are?

So for instance:

// define the period of the range
$period = new DatePeriod($begin, $rangeType, $end);

// iterate through the dates in range
foreach ( $period as $dt ) {
}

This is what I would like to do from the above code:

echo count($period);

Basically I want to know how many time the foreach loop will end up running.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Tom Bird
  • 999
  • 3
  • 17
  • 31

4 Answers4

48

You can use the iterator_count function for this:

echo(iterator_count($period));
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
DiverseAndRemote.com
  • 19,314
  • 10
  • 61
  • 70
  • 9
    Note that `iterator_count` internally iterates over all items to count them. So if the period is large and you iterate over it anyways with foreach you can do the counting yourself, which would be much more efficient. – Fabian Schmengler Jan 23 '13 at 21:52
1

Assuming that you are interested in counting the number of days only (regardless of the interval spec) - thx @mark-amery for bringing this up!

Another more obvious approach would be to diff the 2 dates and get the number of days from the result.

$numDays = $end->diff($begin)->days;
$numDaysFormatted = $end->diff($begin)->format('%d days');

Be sure to validate your GET vars to avoid date warnings / errors.

Better late than never ;-)

EDIT:

If you only have a period object you do have access to the start and end of the period.

$numDays = $period
    ->getEndDate()
    ->diff($period->getStartDate())
    ->days;
4levels
  • 3,134
  • 1
  • 23
  • 22
0

One option to find intervals form the date period is to use diff() method on dateTimes(difference of start and end date) and extract days

https://www.php.net/manual/en/datetime.diff

Sample Code

$period = new DatePeriod($begin, $rangeType, $end);
$startDate = $period->getStartDate();
$endDate   = $period->getEndDate();
$interval  = $startDate->diff($endDate);
echo $interval->days
Sai
  • 539
  • 6
  • 7
  • 2
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel Apr 13 '23 at 10:19
-1
class MyDatePeriod extends DatePeriod
{
    public $dates;

    public function toArray()
    {
        if ($this->dates === null) {
            $this->dates = iterator_to_array($this);
        }

        return $this->dates;
    }
}

$p = new MyDatePeriod(date_create('2008-01-01'),
                      DateInterval::createFromDateString( "+2 days" ),
                      date_create('2008-12-31'));

echo count($p->toArray()) . "\n"; // 183

echo count($p->toArray()) . "\n"; // 183
David
  • 253
  • 1
  • 2
  • 10
  • Nope... if you must solve this with inheritance, at least implement the `Countable` interface instead of over-complicating things like that. But either way, extending DatePeriod is bad practice. – Fabian Schmengler Jan 23 '13 at 22:05
  • 2
    Extending standard libraries is a bad practice? All things electronic just exploded. – David Jan 23 '13 at 22:17
  • Yes, *extending* classes just to add functionality is usually a bad idea. See [Composition over Inheritance](http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance) (or [here](http://en.wikipedia.org/wiki/Composition_over_inheritance) or [here](http://c2.com/cgi/wiki?CompositionInsteadOfInheritance). A clean alternative here is a [Decorator](http://en.wikipedia.org/wiki/Decorator_pattern) because it would allow adding multiple functionality independently. But for this specific case that would be over-engineering. `iterator_count` and `iterator_to_array` do the job well. – Fabian Schmengler Jan 23 '13 at 22:27
  • 2
    You do realize that all of those links you provided actually agree with me right? He wants a DateInterval that has a given property. This is not redefining an apple from an orange scenario which is the point of composition over inheritance (i.e. composition should always be considered, but is not always the correct approach). Decorator pattern is best suited for one to many composition. He did not ask how to abstract a built in type 15 different ways. – David Jan 23 '13 at 23:27
  • If you look closely, the links go further than the usual "has a" vs. "is a" argument. I see that the case is disputable, however you *are* unneccessary restricting yourself with such code. And he does not even want a DatePeriod with an additional property, he wants do do something *with* the DatePeriod: count its items. – Fabian Schmengler Jan 23 '13 at 23:40
  • Sigh, no it is not restricting... if that were the case you would be writing everything in some functional language instead of an object oriented language. As stated before, if this were a one to many operation, or some sort of stateful device, composition would be the way to go. This is not either. – David Jan 23 '13 at 23:50
  • I don't want to get into this but all I wanted to was get each day in between the starting day and end day for a SQL query so that I could pull results from the db for specific range of dates by day – Tom Bird Feb 23 '13 at 09:08
  • 1
    -1; this is pretty obviously ludicrous. You're adding this functionality into a whole separate class (meaning that a raw `DatePeriod`'s iterations can't be counted) all to produce a final syntax - `count($p->toArray())` - that is more complicated and no more performant than the `iterator_count($p)` that the language already gives you. – Mark Amery Dec 23 '17 at 14:41