7

DatePeriod is a PHP class for handling recurring dates. It has a very limited number of methods. So when I want to do basic array functions with the recurring dates, I have to copy it to an array with iterator_to_array. Strangely, copying it seems to clobber it. Any ideas why?

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

echo count(iterator_to_array($p)); //183 

$a=iterator_to_array($p); 
echo count($a); //0 
1
  • sorry to bump a two year old post but Did you manage to find out why this is happening? Commented Aug 26, 2011 at 14:00

3 Answers 3

3

Here's what I'd do. I'd extend DatePeriod and implement a toArray method:

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
Sign up to request clarification or add additional context in comments.

2 Comments

I don't understand why iterator_to_array($this) from inside the class doesn't do the same as iterator_to_array($p) from outside. But I'm sure glad it does! Thanks very much.
It does the same, but I'm caching the result into an instance variable, $dates, so on subsequent calls to toArray there are no more calls to iterator_to_array. I've simply returned the cached result.
3

I wonder if maybe the iterator isn't being re-wound by iterator_to_array(), so the second call starts iterating with the cursor at the end. You could try this:

$p->rewind()
$a=iterator_to_array($p); 

If the iterator is not rewindable, you could try cloning the object before you traverse it, e.g.

$p2 = clone $p;
echo count(iterator_to_array($p2));

$array = iterator_to_array($p);

3 Comments

It appears that DatePeriod does not have a rewind method. :( The documentation says that DatePeriod implements Traversable. But Traversable is an abstract interface that requires Iterator or IteratorAggregate to be implemented (neither of which are mentioned in the DatePeriod docs). IteratorAggregate does not appear to have a public rewind method, so perhaps DatePeriod is a child of it rather than Iterator?
Sadly, clone is not an option. It appears to cause a fatal error, but of what type I don't know since it doesn't show up in the web logs.
As far as I'm concerned the new date and time implementations in PHP 5.3 suck big time.
2

Presumably, the first call traverses all the elements in the iterator (i.e. calls next() until valid() is false). The sensible behaviour is for iterator_to_array to begin the conversion from the current position in the iterator - having it silently rewind would be inflexible, and possibly bug inducing.

Try rewinding the iterator before using it again.

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

echo count(iterator_to_array($p)); //183 

$p->rewind(); // Newly added!

$a=iterator_to_array($p); 
echo count($a); //0

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.