123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- <?php
- declare(strict_types=1);
- /**
- * This file is part of the Carbon package.
- *
- * (c) Brian Nesbitt <brian@nesbot.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Tests\CarbonPeriod;
- use Carbon\Carbon;
- use Carbon\CarbonInterval;
- use Carbon\CarbonPeriod;
- use Generator;
- use Tests\AbstractTestCase;
- use Tests\CarbonPeriod\Fixtures\CarbonPeriodFactory;
- class IteratorTest extends AbstractTestCase
- {
- protected $iterationLimit = 100;
- public function testKeyAndCurrentAreCorrectlyInstantiated()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- $this->assertSame(0, $period->key());
- $this->assertInstanceOfCarbon($period->current());
- $this->assertSame('2012-07-04 00:00:00', $period->current()->format('Y-m-d H:i:s'));
- $this->assertTrue($period->valid());
- }
- public function testValidIsCorrectlyInstantiated()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- $this->assertTrue($period->valid());
- }
- public function testCurrentIsAlwaysCarbonInstance()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- foreach ($period as $key => $current) {
- $this->assertInstanceOfCarbon($current);
- $this->assertEquals($current, $period->current());
- $this->assertEquals($current, $period->current);
- }
- }
- public function testKeysAreSequential()
- {
- $keys = [];
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- foreach ($period as $key => $current) {
- $this->assertIsInt($keys[] = $key);
- $this->assertSame($key, $period->key());
- }
- $this->assertSame(array_keys($keys), $keys);
- }
- public function testElementsInLoopAreAlwaysValid()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- foreach ($period as $key => $current) {
- $this->assertTrue($period->valid());
- }
- }
- public function testKeyAndCurrentAreCorrectlyIterated()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- $period->next();
- $this->assertSame(1, $period->key());
- $this->assertSame('2012-07-10 00:00:00', $period->current()->format('Y-m-d H:i:s'));
- $this->assertTrue($period->valid());
- }
- public function testKeyAndCurrentAreCorrectlyRewound()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- $period->next();
- $period->rewind();
- $this->assertSame(0, $period->key());
- $this->assertSame('2012-07-04 00:00:00', $period->current()->format('Y-m-d H:i:s'));
- $this->assertTrue($period->valid());
- }
- public function testKeyAndCurrentAreNullAfterIteration()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- foreach ($period as $key => $current) {
- //
- }
- $this->assertNull($period->key());
- $this->assertNull($period->current());
- $this->assertFalse($period->valid());
- }
- /**
- * @dataProvider dataForIterateBackwardsArguments
- */
- public function testIterateBackwards($arguments, $expected)
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create(...$arguments);
- $interval = new CarbonInterval('P3D');
- $interval->invert = 1;
- $period = $period->setDateInterval($interval);
- $this->assertSame(
- $this->standardizeDates($expected),
- $this->standardizeDates($period)
- );
- }
- public static function dataForIterateBackwardsArguments(): Generator
- {
- yield [
- ['2015-10-15', '2015-10-06'],
- ['2015-10-15', '2015-10-12', '2015-10-09', '2015-10-06'],
- ];
- yield [
- ['2015-10-15', '2015-10-06', CarbonPeriod::EXCLUDE_START_DATE],
- ['2015-10-12', '2015-10-09', '2015-10-06'],
- ];
- yield [
- ['2015-10-15', '2015-10-06', CarbonPeriod::EXCLUDE_END_DATE],
- ['2015-10-15', '2015-10-12', '2015-10-09'],
- ];
- yield [
- ['2015-10-15', '2015-10-06', CarbonPeriod::EXCLUDE_START_DATE | CarbonPeriod::EXCLUDE_END_DATE],
- ['2015-10-12', '2015-10-09'],
- ];
- yield [
- ['2015-10-15', 3],
- ['2015-10-15', '2015-10-12', '2015-10-09'],
- ];
- }
- public function testChangingParametersShouldNotCauseInfiniteLoop()
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create()
- ->setStartDate($start = '2012-07-01')
- ->setEndDate($end = '2012-07-20')
- ->setDateInterval($interval = 'P1D')
- ->setRecurrences($recurrences = 10)
- ->setOptions($options = $periodClass::EXCLUDE_START_DATE | $periodClass::EXCLUDE_END_DATE)
- ->addFilter($filter = function () {
- return true;
- });
- $counter = 0;
- foreach ($period as $current) {
- if (++$counter >= $this->iterationLimit) {
- break;
- }
- $period->removeFilter($filter)
- ->prependFilter($filter)
- ->setFilters([])
- ->setStartDate($start)
- ->setEndDate($end)
- ->invertDateInterval()
- ->setDateInterval($interval)
- ->setRecurrences($recurrences)
- ->setOptions($options)
- ->resetFilters()
- ->addFilter($filter);
- }
- $this->assertLessThan($this->iterationLimit, $counter, 'Changing parameters during the iteration caused an infinite loop.');
- }
- public function testChangeEndDateDuringIteration()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- $results = [];
- foreach ($period as $key => $current) {
- $results[] = sprintf('%s => %s', $key, $current->toDateString());
- if ($current->toDateString() === '2012-07-16') {
- $period = $period->setEndDate($current);
- // Note: Current is no longer valid, because it is now equal to end, which is excluded.
- $this->assertNull($period->key());
- $this->assertNull($period->current());
- $this->assertFalse($period->valid());
- }
- if (\count($results) >= $this->iterationLimit) {
- $this->fail('Infinite loop detected when traversing the period.');
- }
- }
- $this->assertSame(
- ['0 => 2012-07-04', '1 => 2012-07-10', '2 => 2012-07-16'],
- $results
- );
- }
- public function testKeepIncreasingRecurrencesDuringIteration()
- {
- $period = new CarbonPeriod('2012-07-01', $recurrences = 1);
- $results = [];
- foreach ($period as $key => $current) {
- $results[] = sprintf('%s => %s', $key, $current->toDateString());
- if ($recurrences < 4) {
- $period->setRecurrences(++$recurrences);
- // Note: Current is still valid, because we simply extended the period.
- $this->assertSame($key, $period->key());
- $this->assertEquals($current, $period->current());
- $this->assertTrue($period->valid());
- }
- if (\count($results) >= $this->iterationLimit) {
- $this->fail('Infinite loop detected when traversing the period.');
- }
- }
- $this->assertSame(
- ['0 => 2012-07-01', '1 => 2012-07-02', '2 => 2012-07-03', '3 => 2012-07-04'],
- $results
- );
- }
- public function testChangeStartDateDuringIteration()
- {
- $period = new CarbonPeriod('2012-07-01', '2012-07-04');
- $results = [];
- $newStart = new Carbon('2012-07-03');
- foreach ($period as $key => $current) {
- $results[] = sprintf('%s => %s', $key, $current->toDateString());
- if ($current < $newStart) {
- $period->setStartDate($newStart);
- // Note: Current is still valid, because start date is used only for initialization.
- $this->assertEquals($key, $period->key());
- $this->assertEquals($current, $period->current());
- $this->assertTrue($period->valid());
- }
- if (\count($results) >= $this->iterationLimit) {
- $this->fail('Infinite loop detected when traversing the period.');
- }
- }
- $this->assertSame(
- // Note: Results are not affected, because start date is used only for initialization.
- ['0 => 2012-07-01', '1 => 2012-07-02', '2 => 2012-07-03', '3 => 2012-07-04'],
- $results
- );
- }
- public function testChangeDateIntervalDuringIteration()
- {
- $period = new CarbonPeriod('2012-07-01', 3);
- $results = [];
- foreach ($period as $key => $current) {
- $results[] = sprintf('%s => %s', $key, $current->toDateString());
- $period->setDateInterval('P3D');
- // Note: Current is still valid, because changed interval changes only subsequent items.
- $this->assertSame($key, $period->key());
- $this->assertEquals($current, $period->current());
- $this->assertTrue($period->valid());
- if (\count($results) >= $this->iterationLimit) {
- $this->fail('Infinite loop detected when traversing the period.');
- }
- }
- $this->assertSame(
- ['0 => 2012-07-01', '1 => 2012-07-04', '2 => 2012-07-07'],
- $results
- );
- }
- public function testValidateOncePerIteration()
- {
- $period = CarbonPeriodFactory::withCounter($this->periodClass, $counter);
- $period->key();
- $period->current();
- $period->valid();
- $this->assertSame(1, $counter);
- $period->next();
- $this->assertSame(2, $counter);
- $period->key();
- $period->current();
- $period->valid();
- $this->assertSame(2, $counter);
- }
- public function testInvalidateCurrentAfterChangingParameters()
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create('2012-10-01');
- $this->assertInstanceOfCarbon($period->current());
- $period = $period->addFilter($periodClass::END_ITERATION);
- $this->assertNull($period->current());
- }
- public function testTraversePeriodDynamically()
- {
- $period = CarbonPeriodFactory::withEvenDaysFilter($this->periodClass);
- $results = [];
- while ($current = $period->current()) {
- $results[] = $current;
- $period->next();
- if (\count($results) >= $this->iterationLimit) {
- $this->fail('Infinite loop detected when traversing the period.');
- }
- }
- $this->assertSame(
- $this->standardizeDates(['2012-07-04', '2012-07-10', '2012-07-16']),
- $this->standardizeDates($results)
- );
- }
- public function testExtendCompletedIteration()
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create('2018-10-10', '2018-10-11');
- $results = [];
- while ($period->valid()) {
- $results[] = $period->current();
- $period->next();
- }
- $period = $period->setEndDate('2018-10-13');
- while ($period->valid()) {
- $results[] = $period->current();
- $period->next();
- }
- $this->assertSame(
- $this->standardizeDates(['2018-10-10', '2018-10-11', '2018-10-12', '2018-10-13']),
- $this->standardizeDates($results)
- );
- }
- public function testRevalidateCurrentAfterChangeOfParameters()
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create()->setStartDate($start = new Carbon('2018-10-28'));
- $this->assertEquals($start, $period->current());
- $this->assertNotSame($start, $period->current());
- $period = $period->addFilter($excludeStart = function ($date) use ($start) {
- return $date != $start;
- });
- $this->assertNull($period->current());
- $period = $period->removeFilter($excludeStart);
- $this->assertEquals($start, $period->current());
- $this->assertNotSame($start, $period->current());
- }
- public function testRevalidateCurrentAfterEndOfIteration()
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create()->setStartDate($start = new Carbon('2018-10-28'));
- $this->assertEquals($start, $period->current());
- $this->assertNotSame($start, $period->current());
- $period = $period->addFilter($periodClass::END_ITERATION);
- $this->assertNull($period->current());
- $period = $period->removeFilter($periodClass::END_ITERATION);
- $this->assertEquals($start, $period->current());
- $this->assertNotSame($start, $period->current());
- }
- public function testChangeStartDateBeforeIteration()
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create(new Carbon('2018-10-05'), 3)
- ->setStartDate(new Carbon('2018-10-13'))
- ->toggleOptions($periodClass::EXCLUDE_START_DATE, true);
- $this->assertEquals(new Carbon('2018-10-14'), $period->current());
- }
- public function testChangeStartDateAfterStartedIteration()
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create(new Carbon('2018-10-05'), 3);
- $current = $period->current();
- $period->toggleOptions($periodClass::EXCLUDE_START_DATE, true);
- $period->setStartDate(new Carbon('2018-10-13'));
- $this->assertEquals($current, $period->current());
- }
- public function testInvertDateIntervalDuringIteration()
- {
- $periodClass = $this->periodClass;
- $period = new $periodClass('2018-04-11', 5);
- $results = [];
- foreach ($period as $key => $date) {
- $results[] = $date;
- if ($key === 2) {
- $period->invertDateInterval();
- }
- }
- $this->assertSame(
- $this->standardizeDates(['2018-04-11', '2018-04-12', '2018-04-13', '2018-04-12', '2018-04-11']),
- $this->standardizeDates($results)
- );
- }
- public function testManualIteration()
- {
- $period = CarbonPeriodFactory::withStackFilter($this->periodClass);
- $period->rewind();
- $str = '';
- while ($period->valid()) {
- if ($period->key()) {
- $str .= ', ';
- }
- $str .= $period->current()->format('m-d');
- $period->next();
- }
- $this->assertSame('01-01, 01-03', $str);
- }
- public function testSkip()
- {
- $periodClass = $this->periodClass;
- $period = $periodClass::create('2018-05-30', '2018-07-13');
- $output = [];
- foreach ($period as $day) {
- /* @var Carbon $day */
- $output[] = $day->format('Y-m-d');
- if ($day->isSunday()) {
- $this->assertTrue($period->skip(7));
- $output[] = '...';
- }
- }
- $this->assertSame([
- '2018-05-30',
- '2018-05-31',
- '2018-06-01',
- '2018-06-02',
- '2018-06-03',
- '...',
- '2018-06-11',
- '2018-06-12',
- '2018-06-13',
- '2018-06-14',
- '2018-06-15',
- '2018-06-16',
- '2018-06-17',
- '...',
- '2018-06-25',
- '2018-06-26',
- '2018-06-27',
- '2018-06-28',
- '2018-06-29',
- '2018-06-30',
- '2018-07-01',
- '...',
- '2018-07-09',
- '2018-07-10',
- '2018-07-11',
- '2018-07-12',
- '2018-07-13',
- ], $output);
- $this->assertFalse($period->skip());
- $this->assertFalse($period->skip(7));
- }
- public function testLocale()
- {
- /** @var CarbonPeriod $period */
- $period = CarbonPeriodFactory::withStackFilter($this->periodClass)->locale('de');
- $str = '';
- foreach ($period as $key => $date) {
- if ($key) {
- $str .= ', ';
- }
- $str .= $date->isoFormat('MMMM dddd');
- }
- $this->assertSame('Januar Montag, Januar Mittwoch', $str);
- }
- public function testTimezone()
- {
- $period = CarbonPeriodFactory::withStackFilter($this->periodClass)->shiftTimezone('America/Toronto');
- $str = null;
- foreach ($period as $key => $date) {
- $str = $date->format('H e');
- break;
- }
- $this->assertSame('00 America/Toronto', $str);
- }
- }
|