Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!CxGcron-expression/.editorconfignu[root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 trim_trailing_whitespace = true [*.md] trim_trailing_whitespace = false [*.yml] indent_style = space indent_size = 2 PK! wLLcron-expression/CHANGELOG.mdnu[# Change Log ## [2.3.0] - 2019-03-30 ### Added - Added support for DateTimeImmutable via DateTimeInterface - Added support for PHP 7.3 - Started listing projects that use the library ### Changed - Errors should now report a human readable position in the cron expression, instead of starting at 0 ### Fixed - N/A ## [2.2.0] - 2018-06-05 ### Added - Added support for steps larger than field ranges (#6) ## Changed - N/A ### Fixed - Fixed validation for numbers with leading 0s (#12) ## [2.1.0] - 2018-04-06 ### Added - N/A ### Changed - Upgraded to PHPUnit 6 (#2) ### Fixed - Refactored timezones to deal with some inconsistent behavior (#3) - Allow ranges and lists in same expression (#5) - Fixed regression where literals were not converted to their numerical counterpart (#) ## [2.0.0] - 2017-10-12 ### Added - N/A ### Changed - Dropped support for PHP 5.x - Dropped support for the YEAR field, as it was not part of the cron standard ### Fixed - Reworked validation for all the field types - Stepping should now work for 1-indexed fields like Month (#153) ## [1.2.0] - 2017-01-22 ### Added - Added IDE, CodeSniffer, and StyleCI.IO support ### Changed - Switched to PSR-4 Autoloading ### Fixed - 0 step expressions are handled better - Fixed `DayOfMonth` validation to be more strict - Typos ## [1.1.0] - 2016-01-26 ### Added - Support for non-hourly offset timezones - Checks for valid expressions ### Changed - Max Iterations no longer hardcoded for `getRunDate()` - Supports DateTimeImmutable for newer PHP verions ### Fixed - Fixed looping bug for PHP 7 when determining the last specified weekday of a month ## [1.0.3] - 2013-11-23 ### Added - Now supports expressions with any number of extra spaces, tabs, or newlines ### Changed - Using static instead of self in `CronExpression::factory` ### Fixed - Fixes issue [#28](https://github.com/mtdowling/cron-expression/issues/28) where PHP increments of ranges were failing due to PHP casting hyphens to 0 - Only set default timezone if the given $currentTime is not a DateTime instance ([#34](https://github.com/mtdowling/cron-expression/issues/34)) PK!iMg g cron-expression/README.mdnu[PHP Cron Expression Parser ========================== [![Latest Stable Version](https://poser.pugx.org/dragonmantank/cron-expression/v/stable.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Total Downloads](https://poser.pugx.org/dragonmantank/cron-expression/downloads.png)](https://packagist.org/packages/dragonmantank/cron-expression) [![Build Status](https://secure.travis-ci.org/dragonmantank/cron-expression.png)](http://travis-ci.org/dragonmantank/cron-expression) The PHP cron expression parser can parse a CRON expression, determine if it is due to run, calculate the next run date of the expression, and calculate the previous run date of the expression. You can calculate dates far into the future or past by skipping **n** number of matching dates. The parser can handle increments of ranges (e.g. */12, 2-59/3), intervals (e.g. 0-9), lists (e.g. 1,2,3), **W** to find the nearest weekday for a given day of the month, **L** to find the last day of the month, **L** to find the last given weekday of a month, and hash (#) to find the nth weekday of a given month. More information about this fork can be found in the blog post [here](http://ctankersley.com/2017/10/12/cron-expression-update/). tl;dr - v2.0.0 is a major breaking change, and @dragonmantank can better take care of the project in a separate fork. Installing ========== Add the dependency to your project: ```bash composer require dragonmantank/cron-expression ``` Usage ===== ```php isDue(); echo $cron->getNextRunDate()->format('Y-m-d H:i:s'); echo $cron->getPreviousRunDate()->format('Y-m-d H:i:s'); // Works with complex expressions $cron = Cron\CronExpression::factory('3-59/15 6-12 */15 1 2-5'); echo $cron->getNextRunDate()->format('Y-m-d H:i:s'); // Calculate a run date two iterations into the future $cron = Cron\CronExpression::factory('@daily'); echo $cron->getNextRunDate(null, 2)->format('Y-m-d H:i:s'); // Calculate a run date relative to a specific time $cron = Cron\CronExpression::factory('@monthly'); echo $cron->getNextRunDate('2010-01-12 00:00:00')->format('Y-m-d H:i:s'); ``` CRON Expressions ================ A CRON expression is a string representing the schedule for a particular command to execute. The parts of a CRON schedule are as follows: * * * * * - - - - - | | | | | | | | | | | | | | +----- day of week (0 - 7) (Sunday=0 or 7) | | | +---------- month (1 - 12) | | +--------------- day of month (1 - 31) | +-------------------- hour (0 - 23) +------------------------- min (0 - 59) Requirements ============ - PHP 7.0+ - PHPUnit is required to run the unit tests - Composer is required to run the unit tests Projects that Use cron-expression ================================= * Part of the [Laravel Framework](https://github.com/laravel/framework/) * Available as a [Symfony Bundle - setono/cron-expression-bundle](https://github.com/Setono/CronExpressionBundle)PK!ozzcron-expression/LICENSEnu[Copyright (c) 2011 Michael Dowling , 2016 Chris Tankersley , and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!NEWhh1cron-expression/tests/Cron/CronExpressionTest.phpnu[ */ class CronExpressionTest extends TestCase { /** * @covers \Cron\CronExpression::factory */ public function testFactoryRecognizesTemplates() { $this->assertSame('0 0 1 1 *', CronExpression::factory('@annually')->getExpression()); $this->assertSame('0 0 1 1 *', CronExpression::factory('@yearly')->getExpression()); $this->assertSame('0 0 * * 0', CronExpression::factory('@weekly')->getExpression()); } /** * @covers \Cron\CronExpression::__construct * @covers \Cron\CronExpression::getExpression * @covers \Cron\CronExpression::__toString */ public function testParsesCronSchedule() { // '2010-09-10 12:00:00' $cron = CronExpression::factory('1 2-4 * 4,5,6 */3'); $this->assertSame('1', $cron->getExpression(CronExpression::MINUTE)); $this->assertSame('2-4', $cron->getExpression(CronExpression::HOUR)); $this->assertSame('*', $cron->getExpression(CronExpression::DAY)); $this->assertSame('4,5,6', $cron->getExpression(CronExpression::MONTH)); $this->assertSame('*/3', $cron->getExpression(CronExpression::WEEKDAY)); $this->assertSame('1 2-4 * 4,5,6 */3', $cron->getExpression()); $this->assertSame('1 2-4 * 4,5,6 */3', (string) $cron); $this->assertNull($cron->getExpression('foo')); } /** * @covers \Cron\CronExpression::__construct * @covers \Cron\CronExpression::getExpression * @covers \Cron\CronExpression::__toString * @expectedException \InvalidArgumentException * @expectedExceptionMessage Invalid CRON field value A at position 0 */ public function testParsesCronScheduleThrowsAnException() { CronExpression::factory('A 1 2 3 4'); } /** * @covers \Cron\CronExpression::__construct * @covers \Cron\CronExpression::getExpression * @dataProvider scheduleWithDifferentSeparatorsProvider */ public function testParsesCronScheduleWithAnySpaceCharsAsSeparators($schedule, array $expected) { $cron = CronExpression::factory($schedule); $this->assertSame($expected[0], $cron->getExpression(CronExpression::MINUTE)); $this->assertSame($expected[1], $cron->getExpression(CronExpression::HOUR)); $this->assertSame($expected[2], $cron->getExpression(CronExpression::DAY)); $this->assertSame($expected[3], $cron->getExpression(CronExpression::MONTH)); $this->assertSame($expected[4], $cron->getExpression(CronExpression::WEEKDAY)); } /** * Data provider for testParsesCronScheduleWithAnySpaceCharsAsSeparators * * @return array */ public static function scheduleWithDifferentSeparatorsProvider() { return array( array("*\t*\t*\t*\t*\t", array('*', '*', '*', '*', '*', '*')), array("* * * * * ", array('*', '*', '*', '*', '*', '*')), array("* \t * \t * \t * \t * \t", array('*', '*', '*', '*', '*', '*')), array("*\t \t*\t \t*\t \t*\t \t*\t \t", array('*', '*', '*', '*', '*', '*')), ); } /** * @covers \Cron\CronExpression::__construct * @covers \Cron\CronExpression::setExpression * @covers \Cron\CronExpression::setPart * @expectedException InvalidArgumentException */ public function testInvalidCronsWillFail() { // Only four values $cron = CronExpression::factory('* * * 1'); } /** * @covers \Cron\CronExpression::setPart * @expectedException InvalidArgumentException */ public function testInvalidPartsWillFail() { // Only four values $cron = CronExpression::factory('* * * * *'); $cron->setPart(1, 'abc'); } /** * Data provider for cron schedule * * @return array */ public function scheduleProvider() { return array( array('*/2 */2 * * *', '2015-08-10 21:47:27', '2015-08-10 22:00:00', false), array('* * * * *', '2015-08-10 21:50:37', '2015-08-10 21:50:00', true), array('* 20,21,22 * * *', '2015-08-10 21:50:00', '2015-08-10 21:50:00', true), // Handles CSV values array('* 20,22 * * *', '2015-08-10 21:50:00', '2015-08-10 22:00:00', false), // CSV values can be complex array('7-9 * */9 * *', '2015-08-10 22:02:33', '2015-08-10 22:07:00', false), // 15th minute, of the second hour, every 15 days, in January, every Friday array('1 * * * 7', '2015-08-10 21:47:27', '2015-08-16 00:01:00', false), // Test with exact times array('47 21 * * *', strtotime('2015-08-10 21:47:30'), '2015-08-10 21:47:00', true), // Test Day of the week (issue #1) // According cron implementation, 0|7 = sunday, 1 => monday, etc array('* * * * 0', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false), array('* * * * 7', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false), array('* * * * 1', strtotime('2011-06-15 23:09:00'), '2011-06-20 00:00:00', false), // Should return the sunday date as 7 equals 0 array('0 0 * * MON,SUN', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false), array('0 0 * * 1,7', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false), array('0 0 * * 0-4', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false), array('0 0 * * 7-4', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false), array('0 0 * * 4-7', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false), array('0 0 * * 7-3', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false), array('0 0 * * 3-7', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false), array('0 0 * * 3-7', strtotime('2011-06-18 23:09:00'), '2011-06-19 00:00:00', false), // Test lists of values and ranges (Abhoryo) array('0 0 * * 2-7', strtotime('2011-06-20 23:09:00'), '2011-06-21 00:00:00', false), array('0 0 * * 2-7', strtotime('2011-06-18 23:09:00'), '2011-06-19 00:00:00', false), array('0 0 * * 4-7', strtotime('2011-07-19 00:00:00'), '2011-07-21 00:00:00', false), // Test increments of ranges array('0-12/4 * * * *', strtotime('2011-06-20 12:04:00'), '2011-06-20 12:04:00', true), array('4-59/2 * * * *', strtotime('2011-06-20 12:04:00'), '2011-06-20 12:04:00', true), array('4-59/2 * * * *', strtotime('2011-06-20 12:06:00'), '2011-06-20 12:06:00', true), array('4-59/3 * * * *', strtotime('2011-06-20 12:06:00'), '2011-06-20 12:07:00', false), // Test Day of the Week and the Day of the Month (issue #1) array('0 0 1 1 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false), array('0 0 1 JAN 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false), array('0 0 1 * 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false), // Test the W day of the week modifier for day of the month field array('0 0 2W * *', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true), array('0 0 1W * *', strtotime('2011-05-01 00:00:00'), '2011-05-02 00:00:00', false), array('0 0 1W * *', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true), array('0 0 3W * *', strtotime('2011-07-01 00:00:00'), '2011-07-04 00:00:00', false), array('0 0 16W * *', strtotime('2011-07-01 00:00:00'), '2011-07-15 00:00:00', false), array('0 0 28W * *', strtotime('2011-07-01 00:00:00'), '2011-07-28 00:00:00', false), array('0 0 30W * *', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false), array('0 0 31W * *', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false), // Test the last weekday of a month array('* * * * 5L', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false), array('* * * * 6L', strtotime('2011-07-01 00:00:00'), '2011-07-30 00:00:00', false), array('* * * * 7L', strtotime('2011-07-01 00:00:00'), '2011-07-31 00:00:00', false), array('* * * * 1L', strtotime('2011-07-24 00:00:00'), '2011-07-25 00:00:00', false), array('* * * 1 5L', strtotime('2011-12-25 00:00:00'), '2012-01-27 00:00:00', false), // Test the hash symbol for the nth weekday of a given month array('* * * * 5#2', strtotime('2011-07-01 00:00:00'), '2011-07-08 00:00:00', false), array('* * * * 5#1', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true), array('* * * * 3#4', strtotime('2011-07-01 00:00:00'), '2011-07-27 00:00:00', false), // Issue #7, documented example failed ['3-59/15 6-12 */15 1 2-5', strtotime('2017-01-08 00:00:00'), '2017-01-31 06:03:00', false], // https://github.com/laravel/framework/commit/07d160ac3cc9764d5b429734ffce4fa311385403 ['* * * * MON-FRI', strtotime('2017-01-08 00:00:00'), strtotime('2017-01-09 00:00:00'), false], ['* * * * TUE', strtotime('2017-01-08 00:00:00'), strtotime('2017-01-10 00:00:00'), false], ); } /** * @covers \Cron\CronExpression::isDue * @covers \Cron\CronExpression::getNextRunDate * @covers \Cron\DayOfMonthField * @covers \Cron\DayOfWeekField * @covers \Cron\MinutesField * @covers \Cron\HoursField * @covers \Cron\MonthField * @covers \Cron\CronExpression::getRunDate * @dataProvider scheduleProvider */ public function testDeterminesIfCronIsDue($schedule, $relativeTime, $nextRun, $isDue) { $relativeTimeString = is_int($relativeTime) ? date('Y-m-d H:i:s', $relativeTime) : $relativeTime; // Test next run date $cron = CronExpression::factory($schedule); if (is_string($relativeTime)) { $relativeTime = new DateTime($relativeTime); } elseif (is_int($relativeTime)) { $relativeTime = date('Y-m-d H:i:s', $relativeTime); } if (is_string($nextRun)) { $nextRunDate = new DateTime($nextRun); } elseif (is_int($nextRun)) { $nextRunDate = new DateTime(); $nextRunDate->setTimestamp($nextRun); } $this->assertSame($isDue, $cron->isDue($relativeTime)); $next = $cron->getNextRunDate($relativeTime, 0, true); $this->assertEquals($nextRunDate, $next); } /** * @covers \Cron\CronExpression::isDue */ public function testIsDueHandlesDifferentDates() { $cron = CronExpression::factory('* * * * *'); $this->assertTrue($cron->isDue()); $this->assertTrue($cron->isDue('now')); $this->assertTrue($cron->isDue(new DateTime('now'))); $this->assertTrue($cron->isDue(date('Y-m-d H:i'))); $this->assertTrue($cron->isDue(new DateTimeImmutable('now'))); } /** * @covers \Cron\CronExpression::isDue */ public function testIsDueHandlesDifferentDefaultTimezones() { $originalTimezone = date_default_timezone_get(); $cron = CronExpression::factory('0 15 * * 3'); //Wednesday at 15:00 $date = '2014-01-01 15:00'; //Wednesday date_default_timezone_set('UTC'); $this->assertTrue($cron->isDue(new DateTime($date), 'UTC')); $this->assertFalse($cron->isDue(new DateTime($date), 'Europe/Amsterdam')); $this->assertFalse($cron->isDue(new DateTime($date), 'Asia/Tokyo')); date_default_timezone_set('Europe/Amsterdam'); $this->assertFalse($cron->isDue(new DateTime($date), 'UTC')); $this->assertTrue($cron->isDue(new DateTime($date), 'Europe/Amsterdam')); $this->assertFalse($cron->isDue(new DateTime($date), 'Asia/Tokyo')); date_default_timezone_set('Asia/Tokyo'); $this->assertFalse($cron->isDue(new DateTime($date), 'UTC')); $this->assertFalse($cron->isDue(new DateTime($date), 'Europe/Amsterdam')); $this->assertTrue($cron->isDue(new DateTime($date), 'Asia/Tokyo')); date_default_timezone_set($originalTimezone); } /** * @covers \Cron\CronExpression::isDue */ public function testIsDueHandlesDifferentSuppliedTimezones() { $cron = CronExpression::factory('0 15 * * 3'); //Wednesday at 15:00 $date = '2014-01-01 15:00'; //Wednesday $this->assertTrue($cron->isDue(new DateTime($date, new DateTimeZone('UTC')), 'UTC')); $this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('UTC')), 'Europe/Amsterdam')); $this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('UTC')), 'Asia/Tokyo')); $this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('Europe/Amsterdam')), 'UTC')); $this->assertTrue($cron->isDue(new DateTime($date, new DateTimeZone('Europe/Amsterdam')), 'Europe/Amsterdam')); $this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('Europe/Amsterdam')), 'Asia/Tokyo')); $this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('Asia/Tokyo')), 'UTC')); $this->assertFalse($cron->isDue(new DateTime($date, new DateTimeZone('Asia/Tokyo')), 'Europe/Amsterdam')); $this->assertTrue($cron->isDue(new DateTime($date, new DateTimeZone('Asia/Tokyo')), 'Asia/Tokyo')); } /** * @covers Cron\CronExpression::isDue */ public function testIsDueHandlesDifferentTimezonesAsArgument() { $cron = CronExpression::factory('0 15 * * 3'); //Wednesday at 15:00 $date = '2014-01-01 15:00'; //Wednesday $utc = new \DateTimeZone('UTC'); $amsterdam = new \DateTimeZone('Europe/Amsterdam'); $tokyo = new \DateTimeZone('Asia/Tokyo'); $this->assertTrue($cron->isDue(new DateTime($date, $utc), 'UTC')); $this->assertFalse($cron->isDue(new DateTime($date, $amsterdam), 'UTC')); $this->assertFalse($cron->isDue(new DateTime($date, $tokyo), 'UTC')); $this->assertFalse($cron->isDue(new DateTime($date, $utc), 'Europe/Amsterdam')); $this->assertTrue($cron->isDue(new DateTime($date, $amsterdam), 'Europe/Amsterdam')); $this->assertFalse($cron->isDue(new DateTime($date, $tokyo), 'Europe/Amsterdam')); $this->assertFalse($cron->isDue(new DateTime($date, $utc), 'Asia/Tokyo')); $this->assertFalse($cron->isDue(new DateTime($date, $amsterdam), 'Asia/Tokyo')); $this->assertTrue($cron->isDue(new DateTime($date, $tokyo), 'Asia/Tokyo')); } /** * @covers Cron\CronExpression::isDue */ public function testRecognisesTimezonesAsPartOfDateTime() { $cron = CronExpression::factory("0 7 * * *"); $tzCron = "America/New_York"; $tzServer = new \DateTimeZone("Europe/London"); $dtCurrent = \DateTime::createFromFormat("!Y-m-d H:i:s", "2017-10-17 10:00:00", $tzServer); $dtPrev = $cron->getPreviousRunDate($dtCurrent, 0, true, $tzCron); $this->assertEquals('1508151600 : 2017-10-16T07:00:00-04:00 : America/New_York', $dtPrev->format("U \: c \: e")); $dtCurrent = \DateTimeImmutable::createFromFormat("!Y-m-d H:i:s", "2017-10-17 10:00:00", $tzServer); $dtPrev = $cron->getPreviousRunDate($dtCurrent, 0, true, $tzCron); $this->assertEquals('1508151600 : 2017-10-16T07:00:00-04:00 : America/New_York', $dtPrev->format("U \: c \: e")); $dtCurrent = \DateTimeImmutable::createFromFormat("!Y-m-d H:i:s", "2017-10-17 10:00:00", $tzServer); $dtPrev = $cron->getPreviousRunDate($dtCurrent->format("c"), 0, true, $tzCron); $this->assertEquals('1508151600 : 2017-10-16T07:00:00-04:00 : America/New_York', $dtPrev->format("U \: c \: e")); $dtCurrent = \DateTimeImmutable::createFromFormat("!Y-m-d H:i:s", "2017-10-17 10:00:00", $tzServer); $dtPrev = $cron->getPreviousRunDate($dtCurrent->format("\@U"), 0, true, $tzCron); $this->assertEquals('1508151600 : 2017-10-16T07:00:00-04:00 : America/New_York', $dtPrev->format("U \: c \: e")); } /** * @covers \Cron\CronExpression::getPreviousRunDate */ public function testCanGetPreviousRunDates() { $cron = CronExpression::factory('* * * * *'); $next = $cron->getNextRunDate('now'); $two = $cron->getNextRunDate('now', 1); $this->assertEquals($next, $cron->getPreviousRunDate($two)); $cron = CronExpression::factory('* */2 * * *'); $next = $cron->getNextRunDate('now'); $two = $cron->getNextRunDate('now', 1); $this->assertEquals($next, $cron->getPreviousRunDate($two)); $cron = CronExpression::factory('* * * */2 *'); $next = $cron->getNextRunDate('now'); $two = $cron->getNextRunDate('now', 1); $this->assertEquals($next, $cron->getPreviousRunDate($two)); } /** * @covers \Cron\CronExpression::getMultipleRunDates */ public function testProvidesMultipleRunDates() { $cron = CronExpression::factory('*/2 * * * *'); $this->assertEquals(array( new DateTime('2008-11-09 00:00:00'), new DateTime('2008-11-09 00:02:00'), new DateTime('2008-11-09 00:04:00'), new DateTime('2008-11-09 00:06:00') ), $cron->getMultipleRunDates(4, '2008-11-09 00:00:00', false, true)); } /** * @covers \Cron\CronExpression::getMultipleRunDates * @covers \Cron\CronExpression::setMaxIterationCount */ public function testProvidesMultipleRunDatesForTheFarFuture() { // Fails with the default 1000 iteration limit $cron = CronExpression::factory('0 0 12 1 *'); $cron->setMaxIterationCount(2000); $this->assertEquals(array( new DateTime('2016-01-12 00:00:00'), new DateTime('2017-01-12 00:00:00'), new DateTime('2018-01-12 00:00:00'), new DateTime('2019-01-12 00:00:00'), new DateTime('2020-01-12 00:00:00'), new DateTime('2021-01-12 00:00:00'), new DateTime('2022-01-12 00:00:00'), new DateTime('2023-01-12 00:00:00'), new DateTime('2024-01-12 00:00:00'), ), $cron->getMultipleRunDates(9, '2015-04-28 00:00:00', false, true)); } /** * @covers \Cron\CronExpression */ public function testCanIterateOverNextRuns() { $cron = CronExpression::factory('@weekly'); $nextRun = $cron->getNextRunDate("2008-11-09 08:00:00"); $this->assertEquals($nextRun, new DateTime("2008-11-16 00:00:00")); // true is cast to 1 $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", true, true); $this->assertEquals($nextRun, new DateTime("2008-11-16 00:00:00")); // You can iterate over them $nextRun = $cron->getNextRunDate($cron->getNextRunDate("2008-11-09 00:00:00", 1, true), 1, true); $this->assertEquals($nextRun, new DateTime("2008-11-23 00:00:00")); // You can skip more than one $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", 2, true); $this->assertEquals($nextRun, new DateTime("2008-11-23 00:00:00")); $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", 3, true); $this->assertEquals($nextRun, new DateTime("2008-11-30 00:00:00")); } /** * @covers \Cron\CronExpression::getRunDate */ public function testGetRunDateHandlesDifferentDates() { $cron = CronExpression::factory('@weekly'); $date = new DateTime("2019-03-10 00:00:00"); $this->assertEquals($date, $cron->getNextRunDate("2019-03-03 08:00:00")); $this->assertEquals($date, $cron->getNextRunDate(new DateTime("2019-03-03 08:00:00"))); $this->assertEquals($date, $cron->getNextRunDate(new DateTimeImmutable("2019-03-03 08:00:00"))); } /** * @covers \Cron\CronExpression::getRunDate */ public function testSkipsCurrentDateByDefault() { $cron = CronExpression::factory('* * * * *'); $current = new DateTime('now'); $next = $cron->getNextRunDate($current); $nextPrev = $cron->getPreviousRunDate($next); $this->assertSame($current->format('Y-m-d H:i:00'), $nextPrev->format('Y-m-d H:i:s')); } /** * @covers \Cron\CronExpression::getRunDate * @ticket 7 */ public function testStripsForSeconds() { $cron = CronExpression::factory('* * * * *'); $current = new DateTime('2011-09-27 10:10:54'); $this->assertSame('2011-09-27 10:11:00', $cron->getNextRunDate($current)->format('Y-m-d H:i:s')); } /** * @covers \Cron\CronExpression::getRunDate */ public function testFixesPhpBugInDateIntervalMonth() { $cron = CronExpression::factory('0 0 27 JAN *'); $this->assertSame('2011-01-27 00:00:00', $cron->getPreviousRunDate('2011-08-22 00:00:00')->format('Y-m-d H:i:s')); } public function testIssue29() { $cron = CronExpression::factory('@weekly'); $this->assertSame( '2013-03-10 00:00:00', $cron->getPreviousRunDate('2013-03-17 00:00:00')->format('Y-m-d H:i:s') ); } /** * @see https://github.com/mtdowling/cron-expression/issues/20 */ public function testIssue20() { $e = CronExpression::factory('* * * * MON#1'); $this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00'))); $this->assertFalse($e->isDue(new DateTime('2014-04-14 00:00:00'))); $this->assertFalse($e->isDue(new DateTime('2014-04-21 00:00:00'))); $e = CronExpression::factory('* * * * SAT#2'); $this->assertFalse($e->isDue(new DateTime('2014-04-05 00:00:00'))); $this->assertTrue($e->isDue(new DateTime('2014-04-12 00:00:00'))); $this->assertFalse($e->isDue(new DateTime('2014-04-19 00:00:00'))); $e = CronExpression::factory('* * * * SUN#3'); $this->assertFalse($e->isDue(new DateTime('2014-04-13 00:00:00'))); $this->assertTrue($e->isDue(new DateTime('2014-04-20 00:00:00'))); $this->assertFalse($e->isDue(new DateTime('2014-04-27 00:00:00'))); } /** * @covers \Cron\CronExpression::getRunDate */ public function testKeepOriginalTime() { $now = new \DateTime; $strNow = $now->format(DateTime::ISO8601); $cron = CronExpression::factory('0 0 * * *'); $cron->getPreviousRunDate($now); $this->assertSame($strNow, $now->format(DateTime::ISO8601)); } /** * @covers \Cron\CronExpression::__construct * @covers \Cron\CronExpression::factory * @covers \Cron\CronExpression::isValidExpression * @covers \Cron\CronExpression::setExpression * @covers \Cron\CronExpression::setPart */ public function testValidationWorks() { // Invalid. Only four values $this->assertFalse(CronExpression::isValidExpression('* * * 1')); // Valid $this->assertTrue(CronExpression::isValidExpression('* * * * 1')); // Issue #156, 13 is an invalid month $this->assertFalse(CronExpression::isValidExpression("* * * 13 * ")); // Issue #155, 90 is an invalid second $this->assertFalse(CronExpression::isValidExpression('90 * * * *')); // Issue #154, 24 is an invalid hour $this->assertFalse(CronExpression::isValidExpression("0 24 1 12 0")); // Issue #125, this is just all sorts of wrong $this->assertFalse(CronExpression::isValidExpression('990 14 * * mon-fri0345345')); // see https://github.com/dragonmantank/cron-expression/issues/5 $this->assertTrue(CronExpression::isValidExpression('2,17,35,47 5-7,11-13 * * *')); } /** * Makes sure that 00 is considered a valid value for 0-based fields * cronie allows numbers with a leading 0, so adding support for this as well * * @see https://github.com/dragonmantank/cron-expression/issues/12 */ public function testDoubleZeroIsValid() { $this->assertTrue(CronExpression::isValidExpression('00 * * * *')); $this->assertTrue(CronExpression::isValidExpression('01 * * * *')); $this->assertTrue(CronExpression::isValidExpression('* 00 * * *')); $this->assertTrue(CronExpression::isValidExpression('* 01 * * *')); $e = CronExpression::factory('00 * * * *'); $this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00'))); $e = CronExpression::factory('01 * * * *'); $this->assertTrue($e->isDue(new DateTime('2014-04-07 00:01:00'))); $e = CronExpression::factory('* 00 * * *'); $this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00'))); $e = CronExpression::factory('* 01 * * *'); $this->assertTrue($e->isDue(new DateTime('2014-04-07 01:00:00'))); } /** * Ranges with large steps should "wrap around" to the appropriate value * cronie allows for steps that are larger than the range of a field, with it wrapping around like a ring buffer. We * should do the same. * * @see https://github.com/dragonmantank/cron-expression/issues/6 */ public function testRangesWrapAroundWithLargeSteps() { $f = new MonthField(); $this->assertTrue($f->validate('*/123')); $this->assertSame([4], $f->getRangeForExpression('*/123', 12)); $e = CronExpression::factory('* * * */123 *'); $this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00'))); $nextRunDate = $e->getNextRunDate(new DateTime('2014-04-07 00:00:00')); $this->assertSame('2014-04-07 00:01:00', $nextRunDate->format('Y-m-d H:i:s')); $nextRunDate = $e->getNextRunDate(new DateTime('2014-05-07 00:00:00')); $this->assertSame('2015-04-01 00:00:00', $nextRunDate->format('Y-m-d H:i:s')); } /** * When there is an issue with a field, we should report the human readable position * * @see https://github.com/dragonmantank/cron-expression/issues/29 */ public function testFieldPositionIsHumanAdjusted() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage("6 is not a valid position"); $e = CronExpression::factory('0 * * * * ? *'); } } PK!;<<2cron-expression/tests/Cron/DayOfMonthFieldTest.phpnu[ */ class DayOfMonthFieldTest extends TestCase { /** * @covers \Cron\DayOfMonthField::validate */ public function testValidatesField() { $f = new DayOfMonthField(); $this->assertTrue($f->validate('1')); $this->assertTrue($f->validate('*')); $this->assertTrue($f->validate('L')); $this->assertTrue($f->validate('5W')); $this->assertTrue($f->validate('01')); $this->assertFalse($f->validate('5W,L')); $this->assertFalse($f->validate('1.')); } /** * @covers \Cron\DayOfMonthField::isSatisfiedBy */ public function testChecksIfSatisfied() { $f = new DayOfMonthField(); $this->assertTrue($f->isSatisfiedBy(new DateTime(), '?')); $this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?')); } /** * @covers \Cron\DayOfMonthField::increment */ public function testIncrementsDate() { $d = new DateTime('2011-03-15 11:15:00'); $f = new DayOfMonthField(); $f->increment($d); $this->assertSame('2011-03-16 00:00:00', $d->format('Y-m-d H:i:s')); $d = new DateTime('2011-03-15 11:15:00'); $f->increment($d, true); $this->assertSame('2011-03-14 23:59:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\DayOfMonthField::increment */ public function testIncrementsDateTimeImmutable() { $d = new DateTimeImmutable('2011-03-15 11:15:00'); $f = new DayOfMonthField(); $f->increment($d); $this->assertSame('2011-03-16 00:00:00', $d->format('Y-m-d H:i:s')); } /** * Day of the month cannot accept a 0 value, it must be between 1 and 31 * See Github issue #120 * * @since 2017-01-22 */ public function testDoesNotAccept0Date() { $f = new DayOfMonthField(); $this->assertFalse($f->validate(0)); } } PK!; ; -cron-expression/tests/Cron/HoursFieldTest.phpnu[ */ class HoursFieldTest extends TestCase { /** * @covers \Cron\HoursField::validate */ public function testValidatesField() { $f = new HoursField(); $this->assertTrue($f->validate('1')); $this->assertTrue($f->validate('00')); $this->assertTrue($f->validate('01')); $this->assertTrue($f->validate('*')); $this->assertFalse($f->validate('*/3,1,1-12')); } /** * @covers \Cron\HoursField::isSatisfiedBy */ public function testChecksIfSatisfied() { $f = new HoursField(); $this->assertTrue($f->isSatisfiedBy(new DateTime(), '?')); $this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?')); } /** * @covers \Cron\HoursField::increment */ public function testIncrementsDate() { $d = new DateTime('2011-03-15 11:15:00'); $f = new HoursField(); $f->increment($d); $this->assertSame('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s')); $d->setTime(11, 15, 0); $f->increment($d, true); $this->assertSame('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\HoursField::increment */ public function testIncrementsDateTimeImmutable() { $d = new DateTimeImmutable('2011-03-15 11:15:00'); $f = new HoursField(); $f->increment($d); $this->assertSame('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\HoursField::increment */ public function testIncrementsDateWithThirtyMinuteOffsetTimezone() { $tz = date_default_timezone_get(); date_default_timezone_set('America/St_Johns'); $d = new DateTime('2011-03-15 11:15:00'); $f = new HoursField(); $f->increment($d); $this->assertSame('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s')); $d->setTime(11, 15, 0); $f->increment($d, true); $this->assertSame('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s')); date_default_timezone_set($tz); } /** * @covers \Cron\HoursField::increment */ public function testIncrementDateWithFifteenMinuteOffsetTimezone() { $tz = date_default_timezone_get(); date_default_timezone_set('Asia/Kathmandu'); $d = new DateTime('2011-03-15 11:15:00'); $f = new HoursField(); $f->increment($d); $this->assertSame('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s')); $d->setTime(11, 15, 0); $f->increment($d, true); $this->assertSame('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s')); date_default_timezone_set($tz); } } PK!8/cron-expression/tests/Cron/FieldFactoryTest.phpnu[ */ class FieldFactoryTest extends TestCase { /** * @covers \Cron\FieldFactory::getField */ public function testRetrievesFieldInstances() { $mappings = array( 0 => 'Cron\MinutesField', 1 => 'Cron\HoursField', 2 => 'Cron\DayOfMonthField', 3 => 'Cron\MonthField', 4 => 'Cron\DayOfWeekField', ); $f = new FieldFactory(); foreach ($mappings as $position => $class) { $this->assertSame($class, get_class($f->getField($position))); } } /** * @covers \Cron\FieldFactory::getField * @expectedException InvalidArgumentException */ public function testValidatesFieldPosition() { $f = new FieldFactory(); $f->getField(-1); } } PK!e&C C -cron-expression/tests/Cron/MonthFieldTest.phpnu[ */ class MonthFieldTest extends TestCase { /** * @covers \Cron\MonthField::validate */ public function testValidatesField() { $f = new MonthField(); $this->assertTrue($f->validate('12')); $this->assertTrue($f->validate('*')); $this->assertFalse($f->validate('*/10,2,1-12')); $this->assertFalse($f->validate('1.fix-regexp')); } /** * @covers \Cron\MonthField::isSatisfiedBy */ public function testChecksIfSatisfied() { $f = new MonthField(); $this->assertTrue($f->isSatisfiedBy(new DateTime(), '?')); $this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?')); } /** * @covers \Cron\MonthField::increment */ public function testIncrementsDate() { $d = new DateTime('2011-03-15 11:15:00'); $f = new MonthField(); $f->increment($d); $this->assertSame('2011-04-01 00:00:00', $d->format('Y-m-d H:i:s')); $d = new DateTime('2011-03-15 11:15:00'); $f->increment($d, true); $this->assertSame('2011-02-28 23:59:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\MonthField::increment */ public function testIncrementsDateTimeImmutable() { $d = new DateTimeImmutable('2011-03-15 11:15:00'); $f = new MonthField(); $f->increment($d); $this->assertSame('2011-04-01 00:00:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\MonthField::increment */ public function testIncrementsDateWithThirtyMinuteTimezone() { $tz = date_default_timezone_get(); date_default_timezone_set('America/St_Johns'); $d = new DateTime('2011-03-31 11:59:59'); $f = new MonthField(); $f->increment($d); $this->assertSame('2011-04-01 00:00:00', $d->format('Y-m-d H:i:s')); $d = new DateTime('2011-03-15 11:15:00'); $f->increment($d, true); $this->assertSame('2011-02-28 23:59:00', $d->format('Y-m-d H:i:s')); date_default_timezone_set($tz); } /** * @covers \Cron\MonthField::increment */ public function testIncrementsYearAsNeeded() { $f = new MonthField(); $d = new DateTime('2011-12-15 00:00:00'); $f->increment($d); $this->assertSame('2012-01-01 00:00:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\MonthField::increment */ public function testDecrementsYearAsNeeded() { $f = new MonthField(); $d = new DateTime('2011-01-15 00:00:00'); $f->increment($d, true); $this->assertSame('2010-12-31 23:59:00', $d->format('Y-m-d H:i:s')); } } PK!0|ww1cron-expression/tests/Cron/DayOfWeekFieldTest.phpnu[ */ class DayOfWeekFieldTest extends TestCase { /** * @covers \Cron\DayOfWeekField::validate */ public function testValidatesField() { $f = new DayOfWeekField(); $this->assertTrue($f->validate('1')); $this->assertTrue($f->validate('01')); $this->assertTrue($f->validate('00')); $this->assertTrue($f->validate('*')); $this->assertFalse($f->validate('*/3,1,1-12')); $this->assertTrue($f->validate('SUN-2')); $this->assertFalse($f->validate('1.')); } /** * @covers \Cron\DayOfWeekField::isSatisfiedBy */ public function testChecksIfSatisfied() { $f = new DayOfWeekField(); $this->assertTrue($f->isSatisfiedBy(new DateTime(), '?')); $this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?')); } /** * @covers \Cron\DayOfWeekField::increment */ public function testIncrementsDate() { $d = new DateTime('2011-03-15 11:15:00'); $f = new DayOfWeekField(); $f->increment($d); $this->assertSame('2011-03-16 00:00:00', $d->format('Y-m-d H:i:s')); $d = new DateTime('2011-03-15 11:15:00'); $f->increment($d, true); $this->assertSame('2011-03-14 23:59:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\DayOfWeekField::increment */ public function testIncrementsDateTimeImmutable() { $d = new DateTimeImmutable('2011-03-15 11:15:00'); $f = new DayOfWeekField(); $f->increment($d); $this->assertSame('2011-03-16 00:00:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\DayOfWeekField::isSatisfiedBy * @expectedException InvalidArgumentException * @expectedExceptionMessage Weekday must be a value between 0 and 7. 12 given */ public function testValidatesHashValueWeekday() { $f = new DayOfWeekField(); $this->assertTrue($f->isSatisfiedBy(new DateTime(), '12#1')); } /** * @covers \Cron\DayOfWeekField::isSatisfiedBy * @expectedException InvalidArgumentException * @expectedExceptionMessage There are never more than 5 or less than 1 of a given weekday in a month */ public function testValidatesHashValueNth() { $f = new DayOfWeekField(); $this->assertTrue($f->isSatisfiedBy(new DateTime(), '3#6')); } /** * @covers \Cron\DayOfWeekField::validate */ public function testValidateWeekendHash() { $f = new DayOfWeekField(); $this->assertTrue($f->validate('MON#1')); $this->assertTrue($f->validate('TUE#2')); $this->assertTrue($f->validate('WED#3')); $this->assertTrue($f->validate('THU#4')); $this->assertTrue($f->validate('FRI#5')); $this->assertTrue($f->validate('SAT#1')); $this->assertTrue($f->validate('SUN#3')); $this->assertTrue($f->validate('MON#1,MON#3')); } /** * @covers \Cron\DayOfWeekField::isSatisfiedBy */ public function testHandlesZeroAndSevenDayOfTheWeekValues() { $f = new DayOfWeekField(); $this->assertTrue($f->isSatisfiedBy(new DateTime('2011-09-04 00:00:00'), '0-2')); $this->assertTrue($f->isSatisfiedBy(new DateTime('2011-09-04 00:00:00'), '6-0')); $this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), 'SUN')); $this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), 'SUN#3')); $this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), '0#3')); $this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), '7#3')); } /** * @covers \Cron\DayOfWeekField::isSatisfiedBy */ public function testHandlesLastWeekdayOfTheMonth() { $f = new DayOfWeekField(); $this->assertTrue($f->isSatisfiedBy(new DateTime('2018-12-28 00:00:00'), 'FRIL')); $this->assertTrue($f->isSatisfiedBy(new DateTime('2018-12-28 00:00:00'), '5L')); $this->assertFalse($f->isSatisfiedBy(new DateTime('2018-12-21 00:00:00'), 'FRIL')); $this->assertFalse($f->isSatisfiedBy(new DateTime('2018-12-21 00:00:00'), '5L')); } /** * @see https://github.com/mtdowling/cron-expression/issues/47 */ public function testIssue47() { $f = new DayOfWeekField(); $this->assertFalse($f->validate('mon,')); $this->assertFalse($f->validate('mon-')); $this->assertFalse($f->validate('*/2,')); $this->assertFalse($f->validate('-mon')); $this->assertFalse($f->validate(',1')); $this->assertFalse($f->validate('*-')); $this->assertFalse($f->validate(',-')); } /** * @see https://github.com/laravel/framework/commit/07d160ac3cc9764d5b429734ffce4fa311385403 */ public function testLiteralsExpandProperly() { $f = new DayOfWeekField(); $this->assertTrue($f->validate('MON-FRI')); $this->assertSame([1,2,3,4,5], $f->getRangeForExpression('MON-FRI', 7)); } } PK!O0cron-expression/tests/Cron/AbstractFieldTest.phpnu[ */ class AbstractFieldTest extends TestCase { /** * @covers \Cron\AbstractField::isRange */ public function testTestsIfRange() { $f = new DayOfWeekField(); $this->assertTrue($f->isRange('1-2')); $this->assertFalse($f->isRange('2')); } /** * @covers \Cron\AbstractField::isIncrementsOfRanges */ public function testTestsIfIncrementsOfRanges() { $f = new DayOfWeekField(); $this->assertFalse($f->isIncrementsOfRanges('1-2')); $this->assertTrue($f->isIncrementsOfRanges('1/2')); $this->assertTrue($f->isIncrementsOfRanges('*/2')); $this->assertTrue($f->isIncrementsOfRanges('3-12/2')); } /** * @covers \Cron\AbstractField::isInRange */ public function testTestsIfInRange() { $f = new DayOfWeekField(); $this->assertTrue($f->isInRange('1', '1-2')); $this->assertTrue($f->isInRange('2', '1-2')); $this->assertTrue($f->isInRange('5', '4-12')); $this->assertFalse($f->isInRange('3', '4-12')); $this->assertFalse($f->isInRange('13', '4-12')); } /** * @covers \Cron\AbstractField::isInIncrementsOfRanges */ public function testTestsIfInIncrementsOfRangesOnZeroStartRange() { $f = new MinutesField(); $this->assertTrue($f->isInIncrementsOfRanges('3', '3-59/2')); $this->assertTrue($f->isInIncrementsOfRanges('13', '3-59/2')); $this->assertTrue($f->isInIncrementsOfRanges('15', '3-59/2')); $this->assertTrue($f->isInIncrementsOfRanges('14', '*/2')); $this->assertFalse($f->isInIncrementsOfRanges('2', '3-59/13')); $this->assertFalse($f->isInIncrementsOfRanges('14', '*/13')); $this->assertFalse($f->isInIncrementsOfRanges('14', '3-59/2')); $this->assertFalse($f->isInIncrementsOfRanges('3', '2-59')); $this->assertFalse($f->isInIncrementsOfRanges('3', '2')); $this->assertFalse($f->isInIncrementsOfRanges('3', '*')); $this->assertFalse($f->isInIncrementsOfRanges('0', '*/0')); $this->assertFalse($f->isInIncrementsOfRanges('1', '*/0')); $this->assertTrue($f->isInIncrementsOfRanges('4', '4/1')); $this->assertFalse($f->isInIncrementsOfRanges('14', '4/1')); $this->assertFalse($f->isInIncrementsOfRanges('34', '4/1')); } /** * @covers \Cron\AbstractField::isInIncrementsOfRanges */ public function testTestsIfInIncrementsOfRangesOnOneStartRange() { $f = new MonthField(); $this->assertTrue($f->isInIncrementsOfRanges('3', '3-12/2')); $this->assertFalse($f->isInIncrementsOfRanges('13', '3-12/2')); $this->assertFalse($f->isInIncrementsOfRanges('15', '3-12/2')); $this->assertTrue($f->isInIncrementsOfRanges('3', '*/2')); $this->assertFalse($f->isInIncrementsOfRanges('3', '*/3')); $this->assertTrue($f->isInIncrementsOfRanges('7', '*/3')); $this->assertFalse($f->isInIncrementsOfRanges('14', '3-12/2')); $this->assertFalse($f->isInIncrementsOfRanges('3', '2-12')); $this->assertFalse($f->isInIncrementsOfRanges('3', '2')); $this->assertFalse($f->isInIncrementsOfRanges('3', '*')); $this->assertFalse($f->isInIncrementsOfRanges('0', '*/0')); $this->assertFalse($f->isInIncrementsOfRanges('1', '*/0')); $this->assertTrue($f->isInIncrementsOfRanges('4', '4/1')); $this->assertFalse($f->isInIncrementsOfRanges('14', '4/1')); $this->assertFalse($f->isInIncrementsOfRanges('34', '4/1')); } /** * @covers \Cron\AbstractField::isSatisfied */ public function testTestsIfSatisfied() { $f = new DayOfWeekField(); $this->assertTrue($f->isSatisfied('12', '3-13')); $this->assertFalse($f->isSatisfied('15', '3-7/2')); $this->assertTrue($f->isSatisfied('12', '*')); $this->assertTrue($f->isSatisfied('12', '12')); $this->assertFalse($f->isSatisfied('12', '3-11')); $this->assertFalse($f->isSatisfied('12', '3-7/2')); $this->assertFalse($f->isSatisfied('12', '11')); } /** * Allows ranges and lists to coexist in the same expression * * @see https://github.com/dragonmantank/cron-expression/issues/5 */ public function testAllowRangesAndLists() { $expression = '5-7,11-13'; $f = new HoursField(); $this->assertTrue($f->validate($expression)); } /** * Makes sure that various types of ranges expand out properly * * @see https://github.com/dragonmantank/cron-expression/issues/5 */ public function testGetRangeForExpressionExpandsCorrectly() { $f = new HoursField(); $this->assertSame([5, 6, 7, 11, 12, 13], $f->getRangeForExpression('5-7,11-13', 23)); $this->assertSame(['5', '6', '7', '11', '12', '13'], $f->getRangeForExpression('5,6,7,11,12,13', 23)); $this->assertSame([0, 6, 12, 18], $f->getRangeForExpression('*/6', 23)); $this->assertSame([5, 11], $f->getRangeForExpression('5-13/6', 23)); } } PK!o/cron-expression/tests/Cron/MinutesFieldTest.phpnu[ */ class MinutesFieldTest extends TestCase { /** * @covers \Cron\MinutesField::validate */ public function testValidatesField() { $f = new MinutesField(); $this->assertTrue($f->validate('1')); $this->assertTrue($f->validate('*')); $this->assertFalse($f->validate('*/3,1,1-12')); } /** * @covers \Cron\MinutesField::isSatisfiedBy */ public function testChecksIfSatisfied() { $f = new MinutesField(); $this->assertTrue($f->isSatisfiedBy(new DateTime(), '?')); $this->assertTrue($f->isSatisfiedBy(new DateTimeImmutable(), '?')); } /** * @covers \Cron\MinutesField::increment */ public function testIncrementsDate() { $d = new DateTime('2011-03-15 11:15:00'); $f = new MinutesField(); $f->increment($d); $this->assertSame('2011-03-15 11:16:00', $d->format('Y-m-d H:i:s')); $f->increment($d, true); $this->assertSame('2011-03-15 11:15:00', $d->format('Y-m-d H:i:s')); } /** * @covers \Cron\MinutesField::increment */ public function testIncrementsDateTimeImmutable() { $d = new DateTimeImmutable('2011-03-15 11:15:00'); $f = new MinutesField(); $f->increment($d); $this->assertSame('2011-03-15 11:16:00', $d->format('Y-m-d H:i:s')); } /** * Various bad syntaxes that are reported to work, but shouldn't. * * @author Chris Tankersley * @since 2017-08-18 */ public function testBadSyntaxesShouldNotValidate() { $f = new MinutesField(); $this->assertFalse($f->validate('*-1')); $this->assertFalse($f->validate('1-2-3')); $this->assertFalse($f->validate('-1')); } } PK!״3cron-expression/composer.jsonnu[{ "name": "dragonmantank/cron-expression", "type": "library", "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", "keywords": ["cron", "schedule"], "license": "MIT", "authors": [ { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, { "name": "Chris Tankersley", "email": "chris@ctankersley.com", "homepage": "https://github.com/dragonmantank" } ], "require": { "php": "^7.0" }, "require-dev": { "phpunit/phpunit": "^6.4|^7.0" }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" } }, "autoload-dev": { "psr-4": { "Tests\\": "tests/Cron/" } }, "extra": { "branch-alias": { "dev-master": "2.3-dev" } } } PK!`q+cron-expression/src/Cron/FieldInterface.phpnu[ '0 0 1 1 *', '@annually' => '0 0 1 1 *', '@monthly' => '0 0 1 * *', '@weekly' => '0 0 * * 0', '@daily' => '0 0 * * *', '@hourly' => '0 * * * *' ); if (isset($mappings[$expression])) { $expression = $mappings[$expression]; } return new static($expression, $fieldFactory ?: new FieldFactory()); } /** * Validate a CronExpression. * * @param string $expression The CRON expression to validate. * * @return bool True if a valid CRON expression was passed. False if not. * @see \Cron\CronExpression::factory */ public static function isValidExpression($expression) { try { self::factory($expression); } catch (InvalidArgumentException $e) { return false; } return true; } /** * Parse a CRON expression * * @param string $expression CRON expression (e.g. '8 * * * *') * @param FieldFactory|null $fieldFactory Factory to create cron fields */ public function __construct($expression, FieldFactory $fieldFactory = null) { $this->fieldFactory = $fieldFactory; $this->setExpression($expression); } /** * Set or change the CRON expression * * @param string $value CRON expression (e.g. 8 * * * *) * * @return CronExpression * @throws \InvalidArgumentException if not a valid CRON expression */ public function setExpression($value) { $this->cronParts = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY); if (count($this->cronParts) < 5) { throw new InvalidArgumentException( $value . ' is not a valid CRON expression' ); } foreach ($this->cronParts as $position => $part) { $this->setPart($position, $part); } return $this; } /** * Set part of the CRON expression * * @param int $position The position of the CRON expression to set * @param string $value The value to set * * @return CronExpression * @throws \InvalidArgumentException if the value is not valid for the part */ public function setPart($position, $value) { if (!$this->fieldFactory->getField($position)->validate($value)) { throw new InvalidArgumentException( 'Invalid CRON field value ' . $value . ' at position ' . $position ); } $this->cronParts[$position] = $value; return $this; } /** * Set max iteration count for searching next run dates * * @param int $maxIterationCount Max iteration count when searching for next run date * * @return CronExpression */ public function setMaxIterationCount($maxIterationCount) { $this->maxIterationCount = $maxIterationCount; return $this; } /** * Get a next run date relative to the current date or a specific date * * @param string|\DateTimeInterface $currentTime Relative calculation date * @param int $nth Number of matches to skip before returning a * matching next run date. 0, the default, will return the * current date and time if the next run date falls on the * current date and time. Setting this value to 1 will * skip the first match and go to the second match. * Setting this value to 2 will skip the first 2 * matches and so on. * @param bool $allowCurrentDate Set to TRUE to return the current date if * it matches the cron expression. * @param null|string $timeZone TimeZone to use instead of the system default * * @return \DateTime * @throws \RuntimeException on too many iterations */ public function getNextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false, $timeZone = null) { return $this->getRunDate($currentTime, $nth, false, $allowCurrentDate, $timeZone); } /** * Get a previous run date relative to the current date or a specific date * * @param string|\DateTimeInterface $currentTime Relative calculation date * @param int $nth Number of matches to skip before returning * @param bool $allowCurrentDate Set to TRUE to return the * current date if it matches the cron expression * @param null|string $timeZone TimeZone to use instead of the system default * * @return \DateTime * @throws \RuntimeException on too many iterations * @see \Cron\CronExpression::getNextRunDate */ public function getPreviousRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false, $timeZone = null) { return $this->getRunDate($currentTime, $nth, true, $allowCurrentDate, $timeZone); } /** * Get multiple run dates starting at the current date or a specific date * * @param int $total Set the total number of dates to calculate * @param string|\DateTimeInterface $currentTime Relative calculation date * @param bool $invert Set to TRUE to retrieve previous dates * @param bool $allowCurrentDate Set to TRUE to return the * current date if it matches the cron expression * @param null|string $timeZone TimeZone to use instead of the system default * * @return \DateTime[] Returns an array of run dates */ public function getMultipleRunDates($total, $currentTime = 'now', $invert = false, $allowCurrentDate = false, $timeZone = null) { $matches = array(); for ($i = 0; $i < max(0, $total); $i++) { try { $matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate, $timeZone); } catch (RuntimeException $e) { break; } } return $matches; } /** * Get all or part of the CRON expression * * @param string $part Specify the part to retrieve or NULL to get the full * cron schedule string. * * @return string|null Returns the CRON expression, a part of the * CRON expression, or NULL if the part was specified but not found */ public function getExpression($part = null) { if (null === $part) { return implode(' ', $this->cronParts); } elseif (array_key_exists($part, $this->cronParts)) { return $this->cronParts[$part]; } return null; } /** * Helper method to output the full expression. * * @return string Full CRON expression */ public function __toString() { return $this->getExpression(); } /** * Determine if the cron is due to run based on the current date or a * specific date. This method assumes that the current number of * seconds are irrelevant, and should be called once per minute. * * @param string|\DateTimeInterface $currentTime Relative calculation date * @param null|string $timeZone TimeZone to use instead of the system default * * @return bool Returns TRUE if the cron is due to run or FALSE if not */ public function isDue($currentTime = 'now', $timeZone = null) { $timeZone = $this->determineTimeZone($currentTime, $timeZone); if ('now' === $currentTime) { $currentTime = new DateTime(); } elseif ($currentTime instanceof DateTime) { // } elseif ($currentTime instanceof DateTimeImmutable) { $currentTime = DateTime::createFromFormat('U', $currentTime->format('U')); } else { $currentTime = new DateTime($currentTime); } $currentTime->setTimeZone(new DateTimeZone($timeZone)); // drop the seconds to 0 $currentTime = DateTime::createFromFormat('Y-m-d H:i', $currentTime->format('Y-m-d H:i')); try { return $this->getNextRunDate($currentTime, 0, true)->getTimestamp() === $currentTime->getTimestamp(); } catch (Exception $e) { return false; } } /** * Get the next or previous run date of the expression relative to a date * * @param string|\DateTimeInterface $currentTime Relative calculation date * @param int $nth Number of matches to skip before returning * @param bool $invert Set to TRUE to go backwards in time * @param bool $allowCurrentDate Set to TRUE to return the * current date if it matches the cron expression * @param string|null $timeZone TimeZone to use instead of the system default * * @return \DateTime * @throws \RuntimeException on too many iterations */ protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false, $timeZone = null) { $timeZone = $this->determineTimeZone($currentTime, $timeZone); if ($currentTime instanceof DateTime) { $currentDate = clone $currentTime; } elseif ($currentTime instanceof DateTimeImmutable) { $currentDate = DateTime::createFromFormat('U', $currentTime->format('U')); } else { $currentDate = new DateTime($currentTime ?: 'now'); } $currentDate->setTimeZone(new DateTimeZone($timeZone)); $currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), 0); $nextRun = clone $currentDate; $nth = (int) $nth; // We don't have to satisfy * or null fields $parts = array(); $fields = array(); foreach (self::$order as $position) { $part = $this->getExpression($position); if (null === $part || '*' === $part) { continue; } $parts[$position] = $part; $fields[$position] = $this->fieldFactory->getField($position); } // Set a hard limit to bail on an impossible date for ($i = 0; $i < $this->maxIterationCount; $i++) { foreach ($parts as $position => $part) { $satisfied = false; // Get the field object used to validate this part $field = $fields[$position]; // Check if this is singular or a list if (strpos($part, ',') === false) { $satisfied = $field->isSatisfiedBy($nextRun, $part); } else { foreach (array_map('trim', explode(',', $part)) as $listPart) { if ($field->isSatisfiedBy($nextRun, $listPart)) { $satisfied = true; break; } } } // If the field is not satisfied, then start over if (!$satisfied) { $field->increment($nextRun, $invert, $part); continue 2; } } // Skip this match if needed if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) { $this->fieldFactory->getField(0)->increment($nextRun, $invert, isset($parts[0]) ? $parts[0] : null); continue; } return $nextRun; } // @codeCoverageIgnoreStart throw new RuntimeException('Impossible CRON expression'); // @codeCoverageIgnoreEnd } /** * Workout what timeZone should be used. * * @param string|\DateTimeInterface $currentTime Relative calculation date * @param string|null $timeZone TimeZone to use instead of the system default * * @return string */ protected function determineTimeZone($currentTime, $timeZone) { if (! is_null($timeZone)) { return $timeZone; } if ($currentTime instanceOf DateTimeInterface) { return $currentTime->getTimeZone()->getName(); } return date_default_timezone_get(); } } PK!8bjNN*cron-expression/src/Cron/AbstractField.phpnu[fullRange = range($this->rangeStart, $this->rangeEnd); } /** * Check to see if a field is satisfied by a value * * @param string $dateValue Date value to check * @param string $value Value to test * * @return bool */ public function isSatisfied($dateValue, $value) { if ($this->isIncrementsOfRanges($value)) { return $this->isInIncrementsOfRanges($dateValue, $value); } elseif ($this->isRange($value)) { return $this->isInRange($dateValue, $value); } return $value == '*' || $dateValue == $value; } /** * Check if a value is a range * * @param string $value Value to test * * @return bool */ public function isRange($value) { return strpos($value, '-') !== false; } /** * Check if a value is an increments of ranges * * @param string $value Value to test * * @return bool */ public function isIncrementsOfRanges($value) { return strpos($value, '/') !== false; } /** * Test if a value is within a range * * @param string $dateValue Set date value * @param string $value Value to test * * @return bool */ public function isInRange($dateValue, $value) { $parts = array_map(function($value) { $value = trim($value); $value = $this->convertLiterals($value); return $value; }, explode('-', $value, 2) ); return $dateValue >= $parts[0] && $dateValue <= $parts[1]; } /** * Test if a value is within an increments of ranges (offset[-to]/step size) * * @param string $dateValue Set date value * @param string $value Value to test * * @return bool */ public function isInIncrementsOfRanges($dateValue, $value) { $chunks = array_map('trim', explode('/', $value, 2)); $range = $chunks[0]; $step = isset($chunks[1]) ? $chunks[1] : 0; // No step or 0 steps aren't cool if (is_null($step) || '0' === $step || 0 === $step) { return false; } // Expand the * to a full range if ('*' == $range) { $range = $this->rangeStart . '-' . $this->rangeEnd; } // Generate the requested small range $rangeChunks = explode('-', $range, 2); $rangeStart = $rangeChunks[0]; $rangeEnd = isset($rangeChunks[1]) ? $rangeChunks[1] : $rangeStart; if ($rangeStart < $this->rangeStart || $rangeStart > $this->rangeEnd || $rangeStart > $rangeEnd) { throw new \OutOfRangeException('Invalid range start requested'); } if ($rangeEnd < $this->rangeStart || $rangeEnd > $this->rangeEnd || $rangeEnd < $rangeStart) { throw new \OutOfRangeException('Invalid range end requested'); } // Steps larger than the range need to wrap around and be handled slightly differently than smaller steps if ($step >= $this->rangeEnd) { $thisRange = [$this->fullRange[$step % count($this->fullRange)]]; } else { $thisRange = range($rangeStart, $rangeEnd, $step); } return in_array($dateValue, $thisRange); } /** * Returns a range of values for the given cron expression * * @param string $expression The expression to evaluate * @param int $max Maximum offset for range * * @return array */ public function getRangeForExpression($expression, $max) { $values = array(); $expression = $this->convertLiterals($expression); if (strpos($expression, ',') !== false) { $ranges = explode(',', $expression); $values = []; foreach ($ranges as $range) { $expanded = $this->getRangeForExpression($range, $this->rangeEnd); $values = array_merge($values, $expanded); } return $values; } if ($this->isRange($expression) || $this->isIncrementsOfRanges($expression)) { if (!$this->isIncrementsOfRanges($expression)) { list ($offset, $to) = explode('-', $expression); $offset = $this->convertLiterals($offset); $to = $this->convertLiterals($to); $stepSize = 1; } else { $range = array_map('trim', explode('/', $expression, 2)); $stepSize = isset($range[1]) ? $range[1] : 0; $range = $range[0]; $range = explode('-', $range, 2); $offset = $range[0]; $to = isset($range[1]) ? $range[1] : $max; } $offset = $offset == '*' ? $this->rangeStart : $offset; if ($stepSize >= $this->rangeEnd) { $values = [$this->fullRange[$stepSize % count($this->fullRange)]]; } else { for ($i = $offset; $i <= $to; $i += $stepSize) { $values[] = (int)$i; } } sort($values); } else { $values = array($expression); } return $values; } /** * Convert literal * * @param string $value * @return string */ protected function convertLiterals($value) { if (count($this->literals)) { $key = array_search($value, $this->literals); if ($key !== false) { return (string) $key; } } return $value; } /** * Checks to see if a value is valid for the field * * @param string $value * @return bool */ public function validate($value) { $value = $this->convertLiterals($value); // All fields allow * as a valid value if ('*' === $value) { return true; } if (strpos($value, '/') !== false) { list($range, $step) = explode('/', $value); return $this->validate($range) && filter_var($step, FILTER_VALIDATE_INT); } // Validate each chunk of a list individually if (strpos($value, ',') !== false) { foreach (explode(',', $value) as $listItem) { if (!$this->validate($listItem)) { return false; } } return true; } if (strpos($value, '-') !== false) { if (substr_count($value, '-') > 1) { return false; } $chunks = explode('-', $value); $chunks[0] = $this->convertLiterals($chunks[0]); $chunks[1] = $this->convertLiterals($chunks[1]); if ('*' == $chunks[0] || '*' == $chunks[1]) { return false; } return $this->validate($chunks[0]) && $this->validate($chunks[1]); } if (!is_numeric($value)) { return false; } if (is_float($value) || strpos($value, '.') !== false) { return false; } // We should have a numeric by now, so coerce this into an integer $value = (int) $value; return in_array($value, $this->fullRange, true); } } PK!%": 'cron-expression/src/Cron/HoursField.phpnu[isSatisfied($date->format('H'), $value); } /** * {@inheritDoc} * * @param \DateTime|\DateTimeImmutable &$date * @param string|null $parts */ public function increment(DateTimeInterface &$date, $invert = false, $parts = null) { // Change timezone to UTC temporarily. This will // allow us to go back or forwards and hour even // if DST will be changed between the hours. if (is_null($parts) || $parts == '*') { $timezone = $date->getTimezone(); $date = $date->setTimezone(new DateTimeZone('UTC')); $date = $date->modify(($invert ? '-' : '+') . '1 hour'); $date = $date->setTimezone($timezone); $date = $date->setTime($date->format('H'), $invert ? 59 : 0); return $this; } $parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts); $hours = array(); foreach ($parts as $part) { $hours = array_merge($hours, $this->getRangeForExpression($part, 23)); } $current_hour = $date->format('H'); $position = $invert ? count($hours) - 1 : 0; if (count($hours) > 1) { for ($i = 0; $i < count($hours) - 1; $i++) { if ((!$invert && $current_hour >= $hours[$i] && $current_hour < $hours[$i + 1]) || ($invert && $current_hour > $hours[$i] && $current_hour <= $hours[$i + 1])) { $position = $invert ? $i : $i + 1; break; } } } $hour = $hours[$position]; if ((!$invert && $date->format('H') >= $hour) || ($invert && $date->format('H') <= $hour)) { $date = $date->modify(($invert ? '-' : '+') . '1 day'); $date = $date->setTime($invert ? 23 : 0, $invert ? 59 : 0); } else { $date = $date->setTime($hour, $invert ? 59 : 0); } return $this; } } PK!"*R'cron-expression/src/Cron/MonthField.phpnu[ 'JAN', 2 => 'FEB', 3 => 'MAR', 4 => 'APR', 5 => 'MAY', 6 => 'JUN', 7 => 'JUL', 8 => 'AUG', 9 => 'SEP', 10 => 'OCT', 11 => 'NOV', 12 => 'DEC']; /** * @inheritDoc */ public function isSatisfiedBy(DateTimeInterface $date, $value) { if ($value == '?') { return true; } $value = $this->convertLiterals($value); return $this->isSatisfied($date->format('m'), $value); } /** * @inheritDoc * * @param \DateTime|\DateTimeImmutable &$date */ public function increment(DateTimeInterface &$date, $invert = false) { if ($invert) { $date = $date->modify('last day of previous month')->setTime(23, 59); } else { $date = $date->modify('first day of next month')->setTime(0, 0); } return $this; } } PK!,cron-expression/src/Cron/DayOfMonthField.phpnu[ */ class DayOfMonthField extends AbstractField { /** * @inheritDoc */ protected $rangeStart = 1; /** * @inheritDoc */ protected $rangeEnd = 31; /** * Get the nearest day of the week for a given day in a month * * @param int $currentYear Current year * @param int $currentMonth Current month * @param int $targetDay Target day of the month * * @return \DateTime Returns the nearest date */ private static function getNearestWeekday($currentYear, $currentMonth, $targetDay) { $tday = str_pad($targetDay, 2, '0', STR_PAD_LEFT); $target = DateTime::createFromFormat('Y-m-d', "$currentYear-$currentMonth-$tday"); $currentWeekday = (int) $target->format('N'); if ($currentWeekday < 6) { return $target; } $lastDayOfMonth = $target->format('t'); foreach (array(-1, 1, -2, 2) as $i) { $adjusted = $targetDay + $i; if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) { $target->setDate($currentYear, $currentMonth, $adjusted); if ($target->format('N') < 6 && $target->format('m') == $currentMonth) { return $target; } } } } /** * @inheritDoc */ public function isSatisfiedBy(DateTimeInterface $date, $value) { // ? states that the field value is to be skipped if ($value == '?') { return true; } $fieldValue = $date->format('d'); // Check to see if this is the last day of the month if ($value == 'L') { return $fieldValue == $date->format('t'); } // Check to see if this is the nearest weekday to a particular value if (strpos($value, 'W')) { // Parse the target day $targetDay = substr($value, 0, strpos($value, 'W')); // Find out if the current day is the nearest day of the week return $date->format('j') == self::getNearestWeekday( $date->format('Y'), $date->format('m'), $targetDay )->format('j'); } return $this->isSatisfied($date->format('d'), $value); } /** * @inheritDoc * * @param \DateTime|\DateTimeImmutable &$date */ public function increment(DateTimeInterface &$date, $invert = false) { if ($invert) { $date = $date->modify('previous day')->setTime(23, 59); } else { $date = $date->modify('next day')->setTime(0, 0); } return $this; } /** * @inheritDoc */ public function validate($value) { $basicChecks = parent::validate($value); // Validate that a list don't have W or L if (strpos($value, ',') !== false && (strpos($value, 'W') !== false || strpos($value, 'L') !== false)) { return false; } if (!$basicChecks) { if ($value === 'L') { return true; } if (preg_match('/^(.*)W$/', $value, $matches)) { return $this->validate($matches[1]); } return false; } return $basicChecks; } } PK!α)cron-expression/src/Cron/FieldFactory.phpnu[fields[$position])) { switch ($position) { case 0: $this->fields[$position] = new MinutesField(); break; case 1: $this->fields[$position] = new HoursField(); break; case 2: $this->fields[$position] = new DayOfMonthField(); break; case 3: $this->fields[$position] = new MonthField(); break; case 4: $this->fields[$position] = new DayOfWeekField(); break; default: throw new InvalidArgumentException( ($position + 1) . ' is not a valid position' ); } } return $this->fields[$position]; } } PK!dd+cron-expression/src/Cron/DayOfWeekField.phpnu[ 'MON', 2 => 'TUE', 3 => 'WED', 4 => 'THU', 5 => 'FRI', 6 => 'SAT', 7 => 'SUN']; /** * Constructor */ public function __construct() { $this->nthRange = range(1, 5); parent::__construct(); } /** * @inheritDoc * * @param \DateTime|\DateTimeImmutable $date */ public function isSatisfiedBy(DateTimeInterface $date, $value) { if ($value == '?') { return true; } // Convert text day of the week values to integers $value = $this->convertLiterals($value); $currentYear = $date->format('Y'); $currentMonth = $date->format('m'); $lastDayOfMonth = $date->format('t'); // Find out if this is the last specific weekday of the month if (strpos($value, 'L')) { $weekday = $this->convertLiterals(substr($value, 0, strpos($value, 'L'))); $weekday = str_replace('7', '0', $weekday); $tdate = clone $date; $tdate = $tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth); while ($tdate->format('w') != $weekday) { $tdateClone = new DateTime(); $tdate = $tdateClone ->setTimezone($tdate->getTimezone()) ->setDate($currentYear, $currentMonth, --$lastDayOfMonth); } return $date->format('j') == $lastDayOfMonth; } // Handle # hash tokens if (strpos($value, '#')) { list($weekday, $nth) = explode('#', $value); if (!is_numeric($nth)) { throw new InvalidArgumentException("Hashed weekdays must be numeric, {$nth} given"); } else { $nth = (int) $nth; } // 0 and 7 are both Sunday, however 7 matches date('N') format ISO-8601 if ($weekday === '0') { $weekday = 7; } $weekday = $this->convertLiterals($weekday); // Validate the hash fields if ($weekday < 0 || $weekday > 7) { throw new InvalidArgumentException("Weekday must be a value between 0 and 7. {$weekday} given"); } if (!in_array($nth, $this->nthRange)) { throw new InvalidArgumentException("There are never more than 5 or less than 1 of a given weekday in a month, {$nth} given"); } // The current weekday must match the targeted weekday to proceed if ($date->format('N') != $weekday) { return false; } $tdate = clone $date; $tdate = $tdate->setDate($currentYear, $currentMonth, 1); $dayCount = 0; $currentDay = 1; while ($currentDay < $lastDayOfMonth + 1) { if ($tdate->format('N') == $weekday) { if (++$dayCount >= $nth) { break; } } $tdate = $tdate->setDate($currentYear, $currentMonth, ++$currentDay); } return $date->format('j') == $currentDay; } // Handle day of the week values if (strpos($value, '-')) { $parts = explode('-', $value); if ($parts[0] == '7') { $parts[0] = '0'; } elseif ($parts[1] == '0') { $parts[1] = '7'; } $value = implode('-', $parts); } // Test to see which Sunday to use -- 0 == 7 == Sunday $format = in_array(7, str_split($value)) ? 'N' : 'w'; $fieldValue = $date->format($format); return $this->isSatisfied($fieldValue, $value); } /** * @inheritDoc * * @param \DateTime|\DateTimeImmutable &$date */ public function increment(DateTimeInterface &$date, $invert = false) { if ($invert) { $date = $date->modify('-1 day')->setTime(23, 59, 0); } else { $date = $date->modify('+1 day')->setTime(0, 0, 0); } return $this; } /** * @inheritDoc */ public function validate($value) { $basicChecks = parent::validate($value); if (!$basicChecks) { // Handle the # value if (strpos($value, '#') !== false) { $chunks = explode('#', $value); $chunks[0] = $this->convertLiterals($chunks[0]); if (parent::validate($chunks[0]) && is_numeric($chunks[1]) && in_array($chunks[1], $this->nthRange)) { return true; } } if (preg_match('/^(.*)L$/', $value, $matches)) { return $this->validate($matches[1]); } return false; } return $basicChecks; } } PK!)1*)cron-expression/src/Cron/MinutesField.phpnu[isSatisfied($date->format('i'), $value); } /** * {@inheritDoc} * * @param \DateTime|\DateTimeImmutable &$date * @param string|null $parts */ public function increment(DateTimeInterface &$date, $invert = false, $parts = null) { if (is_null($parts)) { $date = $date->modify(($invert ? '-' : '+') . '1 minute'); return $this; } $parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts); $minutes = array(); foreach ($parts as $part) { $minutes = array_merge($minutes, $this->getRangeForExpression($part, 59)); } $current_minute = $date->format('i'); $position = $invert ? count($minutes) - 1 : 0; if (count($minutes) > 1) { for ($i = 0; $i < count($minutes) - 1; $i++) { if ((!$invert && $current_minute >= $minutes[$i] && $current_minute < $minutes[$i + 1]) || ($invert && $current_minute > $minutes[$i] && $current_minute <= $minutes[$i + 1])) { $position = $invert ? $i : $i + 1; break; } } } if ((!$invert && $current_minute >= $minutes[$position]) || ($invert && $current_minute <= $minutes[$position])) { $date = $date->modify(($invert ? '-' : '+') . '1 hour'); $date = $date->setTime($date->format('H'), $invert ? 59 : 0); } else { $date = $date->setTime($date->format('H'), $minutes[$position]); } return $this; } } PK!37s7s<cron-expression/0e47cd322780c04bf723be752bfa0cd7dc203f45.zipnuIwPK LQ& dragonmantank-cron-expression-65b2d8e/UTU_PK LQCxG3 dragonmantank-cron-expression-65b2d8e/.editorconfigUTU_A @ E9Eׂ.ąO"Cڌ d2I)v+q?Rtn\w1Z&O3X +LV2w-ichn-ڼ<&~qC(%.Y?gPK LQ2 dragonmantank-cron-expression-65b2d8e/CHANGELOG.mdUTU_U]o8|ϯX}Ȗ|5oA^y8LKkH*oH3MZ %qwvfvԣJ/Sz4fwJhNd (8JOrmia,}+]Py2Ovó?r{$회?'idodwuz1WL/Rjv!r0ý㮒K]RcͿ{GZ¸;® sk\eZU6d9T)1Nzi4IyXvqy=ؔVtk/m=0Ɔ1,TșAln=͹/lxR*q tDrgw`˂rsb "/m< Gc,2ܴ tF-Q閨wl->S74;>.?C1 tn +B >T<9˯vqi/$GƉN!8T>3}1DٚϓtLދc6O\,GM~nxw-S%֎>$'tzLiܤ=g7 svkٍX/8}gTü(OxBHlYpg{jk -m.>#K`d҆!/*X 7PgVhu`I䈐ї؈]`QDra4jyr )r\0=bToHLٚ,pCAgWt y@ON1a4&SD%E{$;E5vKgfεLO~}.G07 (Qd7(t`RSġYuZPn]R.wbj DL5V [s.;J>孵)bϑsS/;e'PK LQoz- dragonmantank-cron-expression-65b2d8e/LICENSEUTU_]RK0+F9JhgcipF쮶!h|~|m;3?}e?B Q;u kBjʫ~4 Bqգ_8VMQk@/Q-R\ᄤ`2t ҷH_QOzs6Acs_y;N;EyXO" @wWp1gv&Pw<^w77j$=;L@>CmcSy׆7AG`Nw] }OYͳE FĸpSOcqdo]{B`^(1} WSGZ}+V]{}! 5HoNvkeR[&9 ǰ`%!lZX!Yve;)8,!HDpD%Xdϰľ,WT($U9JR.5R$B`%TF\I%M$Y%Gi3$gU(,IH*`t/Dyy`'1Gp[&|PQDBŖYd@e;خ9A3噒x 1To[Q% d%4 hؑO$ؗF 6%tޔbdPK LQiMg / dragonmantank-cron-expression-65b2d8e/README.mdUTU_V{o6_ F ,]ӤCt]4+lXhlI؇e9<0=wghnKJz=Ƣ wWC‰a;WAte5'cB9&IJ7F1%֫K5Wtt":BȶOډN* ˬ,2VlVcgL(O[b`r3J:SO:b N²:4SiBpLETiUPYK:>Oj*!L_tͼeV #a@*2%F6 Up؉,KNT5tT4gW!Z GNRKrPshc<;Џp@3ECFNPP4'sv:2y$)uԄᶺAdb#@Xΐ#2o2,K}k]$"NN.l t@ËQ~ӆCEfSXPW$e_&>CʏHT^ctpee\,TO~Ž103w.(;%Rń朽7k 0Q ҷYVaiWL[-"{EŠ@ya˰DJ͹LnC5 SIff >|Pe J*Eh%LDTN3: $䁅I%R1Uo >N?q78H6vM&d1o5Z iaq8FPRvM  -pi 8ޮsQ=n-=#6d `(ݍ&hEn7TUZ/ Ps)S'ʑL x-nqл݁67ZV|{9m5JXg 1=p 0wb "1b|sb1E*NCaQKl{xJ)n{*_32١ݥCh_FQ~ME-])v{MƵ Wv{+BPθ[N{޽{k4h}q}mu1(GxfƜk80Ȱd]^qP-\7*aۂU!~4*^eu3Pfo(e ӟ3.ev8៨)#-^Xlן}n\RI}V[ٮ?Oalq\NHQ\^f'U3)/WC17=2+Tō9>٨:Ӌ;cSl7 PK LQ* dragonmantank-cron-expression-65b2d8e/src/UTU_PK LQ/ dragonmantank-cron-expression-65b2d8e/src/Cron/UTU_PK LQ8bjyN@ dragonmantank-cron-expression-65b2d8e/src/Cron/AbstractField.phpUTU_NF=_qVJCC}\6l vWDh ΄Xةg¥]g{LU̹ߏ߼]/׽^AVIJ*^oۃ]8e")>+XVh>1GҜ0f!V뜮h$ۅMCE; I p âa Tx"OX_W%)GI\H  3"/!-{ZqqwbۓZz b4|IaauQѤct$$rZ̿ $pRhMxsg)+R.g6Kd(O(Oޑk&I0/jG>Bs%M? 1J![ў. Kh05 ߬pz-B{"uHqN Uon2_. IH 5eH+R,PCD43dl 4g#L-E}H+mO&0Ϯz*GHy=5X4`o0W(̗IaEf²(m'}Wb CVlgڅ.)&P䄋:#lE։cĝA(*iDYR]udq@/6#=ڈ8_ "o|mvvWo쫃WI{@R.=^Nnj5m;mCJ\1h*kg7T GA 9/&*31'Cx 1|. 'ܗWL{QPE0cۊD0`Ih`T''89}\lDo+D-fET&AH )z [E$zt>1~~%:ਢcG+Z8" c_? ;aИհX=?B#7X9 zj9`|Y?_7\cJ2 l&Y%{ZK@6){yKa9p@Y\K0CEQp<[ bA1NŵD#}q%hhðh7 O6O4l\F _#?zԬ \K!:\Hpے:S)e'xgT.FH[4&gDȣ?cڬ@CPkcU2.er:<%#BHi"Iˑ-ԇA1`䶟˨#Q=fAR.M@'`bDŠZЈ>uroY՟VvJab:)x &FG_2vͳP3<0+J+jTmq0DdKG,- O›V~ύkmvxQ>iǙ{[tZeP2Wj=xm6|PҭI{A*RdZC;1pR^<=Qٛ)I YZfeM>ʯj+AhؖE7-zY[lS^.am AIج9>pgT.ZBZh/Q %XĔ޹bޞ5Mr6yqd[ar&f C-kpgK茌ڴOnӺ` X7jrm񷽵tGB稗=TӋwWWIZc4 h*Y15){gwg[2ӊ v-fBd"VBkl%؈}3^\#8H-;_mj m])uD=>`ꆧQ\Pt ߠXBug4x%cg f/_[%v͌:.wf',7b8k|aEV)U߈( N*,A/Gps?PK LQDL ^L f;A dragonmantank-cron-expression-65b2d8e/src/Cron/CronExpression.phpUTU_[s۶v$WtmN&s]bg,i0 I)Gv97(ٱcz x>xbQlldtxA#F<{QqFQΒ%{x;Z.+Avs&X9 n9B$H_K&r^-Y&Z_TNxkkl7 Ts@ ZrVD4#1u, $Є#bD䤬!Pa$cX 4 L׭'΀YŅs1#@;$J)焖@8i%3-XtbI?@ +G(b5..󢀾2_ŠH/A ~ t*e(# C|E^;x523hOG>W] 9WGo+ ԑKє\3Z=I,(cm_% mf]JbzhE 8zutLcomm{4=r`g/;ÿt>E߃-bG|KZrJH<gQ&x:',H䥦;2SMa3gP$'J_2AM"d~Bx%tdH: Rz] s&O00X eи"KE#~D.j^@WZVbH;6*X1.6*U4(4BeXBEZ,m&J#wpv H /XO``Ld+Ƶl꜋D 𭟦ڽtCfYESx!#DtmTBJg|!gm]v_'Kgʈ^z[=,6ԠGEH& DD=L"B,EJӦ+P۠mLTe׆U)vYE04پc&^53!$֑'|zڔzdOz6zV/cei+rm){I{|RJͦcv2XDs&V*~ I91!ALZ]JM-6誶?(=;Ft /5e @MŪ(aGEL%5CW)v)m?]]\|l}dpWqNo2}xHiV[ө*3GNTpf4тfsoI2萿˂y"e~ɇNcTn+\~m< R)/D{|jևd;$'o<::9{xb mX} ]hkrJ`k "uF mc0Zxt_3D.xNl˘L&0:P*@o<{PVŭQ5D~Б:rEz o] Ŝ8z85&l4~ӁU}(!?ρFlF@܏]^_a3A74Q>-ÂМjٞΙ3#Q0Πk8C*jܪ N96_bu~$EWܧ Nb7]R" h/!mXM쒕.[ ),q>8#h0ч@u+mڕx_ts#;oC 'żjhC.o~e^؝ׁ̄Gbz= ^H*iV-\H29TBص4}f,C 7+T]gdu!Q5fFt&iFnJȂ xWI+lX\M&piQK Yi~kCsz>%\pu#@ 8,-`o(TK s}t*S96pp/󼄝{kF 2XXtQ.4XXչt.\S!Np5bx7Zbb/Gݣ?02USȞ6EcCKC!-bl.BgœuY<+%hro)%sեs3,xى7;,cYjw~L(eDd[=پܞN:N|2w٨V7[ W/z! JӎK7S0vȗ #qYPCb%Lڽ }+&E]uu#D]&ץ ~% D_7W@q@~$쩨ɗHx2=i>kPtΎxةp6w&eg95P?%// /laĈu! ~e'6_Gju!#V-] o [WVo4`@QW]3~ɑ*V+ҦZS\a%PK LQB dragonmantank-cron-expression-65b2d8e/src/Cron/DayOfMonthField.phpUTU_Vmo6_q5Hd;itYlҮh^FmhT2c)zkL0`<>ޏ^n֛ c)qxd6 r~)R>o| WKEqk r '$I䝞vSK8+޹ڰ,ְ f z#̚Cj ]yb`d8B [L LqT2<#m8H?,$<G:vToYs{4f݁Ld+$;!-4J9wo8 \HS \0+<%V+ƝHTe%hFxɳQݩ(9%L4!~wgLx;ٷnB va=pg =ZJ4}Ӎx̍$Ө-Osb#d 7"}ak N$(DPUW,7k{+P-OT%XGϫdL擦l}ԞQTbNxr MpzP\ s*bij7Jwad^ ,x>]_M*gje2UPQ٠R70rxf>!&+[GگkhH-VP}~tYY\`t↷l(nqʪ,,25sg\}  k €! T7,w!< ;Bpe0u7_TMd63%3Rf|827-a..*|4|P/ w^P=Xk#xKOliD=jRH4T*g|zc|h§hs)=E A{J`ovhfTsX=w,?-^{ESE\sQ{ڔ$|TFhۯ94Djj }?/bq3` Z{}'TyZ5c3|܈Pdjͣ/vL3}6tٔzF)X" Vw˫AFqHM OuGplb<߆Bێ[,d]WncyMSɢpQuN)lh7{LԯO_V޲[S-]%+Zo\^hoܦ㝇3KA j6)?PK LQnSMA dragonmantank-cron-expression-65b2d8e/src/Cron/DayOfWeekField.phpUTU_XmSF_ 4q 120C`&@24edUѝ 4ܝ_ C[}C}v=gV˷cuticw/c[:'l )4.Kt,R}ϙL|قLZ+r+ \Yt29\+L{zAhl"/J 3 b=YRM̘ l)𙒟>NѲ";~Pb펡۲z"<*AJ9Ն=lvh\X@ȯ8##(4a|SRLq$ru@m ;&Vk%oى%o;Fb=ηM{IthS4vo˺4O[N c[ QU3J@ GV]9/-ij#JL3P7 rÅT&` lIWWB +چZP 6 df,4 r~H/%bI%Mq ch`LajAd@2pF/ HYKfWYYp9&Mjk',b*iԌƛM~HSi'JZKt_GӚ]Tⴼ@g*|~/%xʹe?I30+¹KMᦲO%+ٙ1ٌM,$ ]CȏG§x羪A}ɼ k8b7Z]um-3z{Sk|!n Nc 3dMʴ<ѭʅmW3Ma<ߨzFUa=g2ZLN@j`LFV ΎwD)6Ay@>̘Lp;SWG6yCCf]Ą3jƼs\aK;dM̖U\5N3s#򌛗oLRͭk%v9r4ҤX{"\M Sgz8d-t`j~鯘󁯛m4U4_H<zo¨wod&\樮VF5cI%˚G*_3%1+]{7qn״42,1 HVV(?f_tI?oe@Y`;HƟjb\{|2=ҽtҀRݹJPK LQα? dragonmantank-cron-expression-65b2d8e/src/Cron/FieldFactory.phpUTU_SMo0 Wp@&[O7u+B\I>Iv.M./ŧG[,Ӹ"oQLoz?E"-_Y 0S5^ي"j!^k+K(EelxɖycgB*j\ 2J-LQ^0TBD!&(tw@P*c۵&z3AT:>x~<]`i`2ʁRcѽvCP(1{*chU 8JGS5[jzH#as;3!8zR X;4Z;BƠkLүfv 0d1óiePdg}eуwTZ/-Bv\ɱ]seC~]RUcl]=*r^Tb+I.Z`C Zq0ԍQV0 n-"S}@1zo f]‚LFo1*ʫ/7Ϻḭ3PK LQ%":B = dragonmantank-cron-expression-65b2d8e/src/Cron/HoursField.phpUTU_UMs0W,3N@Ӵ@ C4\NG7[Hr@Y $Y}V9Ȗ Xp{^)OZTs_ 7='+ sI|.IJ}#ȋuѺ>w3mz?ʘAPRGWQg|]7T˭ڹaHș(RrY"cbjW )!S>eilq߸EK(c3]jA 8zh>J!S5TODE lGA7^;oPK LQ)1*? dragonmantank-cron-expression-65b2d8e/src/Cron/MinutesField.phpUTU_UKs0+63~!i$zizk3ֶ I]rPgow%dOϠh EA>AFϊGv֨tʫLRԵ|D݅ڼ!n^z9MMȇ1LWn-`ڬB\$.B36]mȦj[{2]ɼnCݶB;@A;RWQgΠtu-i~U;6cfg:H˼~油 sON}) ?ePK LQ"*R= dragonmantank-cron-expression-65b2d8e/src/Cron/MonthField.phpUTU_Sn1}W"(4R妒T>]ok#{{eTrf|~w/S<vc#1c0(ne. fA.9Rd a-[Ё6tXqk˸3 X,{<[Mx/\cWFQ$0\S=j8g1dD%= 8 ZǗO=8!̽s+|ʲޔywtrCѭ;\]vd|LƐ*FH;(-89]42Y!"Oq_7-SKі-#0 65&8=Z ytQ1V[݇ &ymO,9|Fy^ e|b#rp{i3ҕwk\'p7u"UЏDH tJ/Y,.,Q{`>zGX@PHy?ﶠɰ5PK LQ, dragonmantank-cron-expression-65b2d8e/tests/UTU_PK LQ1 dragonmantank-cron-expression-65b2d8e/tests/Cron/UTU_PK LQOiF dragonmantank-cron-expression-65b2d8e/tests/Cron/AbstractFieldTest.phpUTU_XN@}WRB8!JA RQP҇ř+]kwE%7KUZK asfٱ-ʐxǂkJYV$7xwJ1Mp#!_.^P)/s˳˯S?pq=&uhѰ$R>pA=`C@G~< x|tDJ8JO%bZG/ae8cy$9]*6l ۀz0(gkVtds}3ٖ0g}soET6t (Ե1hd5٪m.~Jbtzϙ'pL^Z4->li uq!Yۨm7ݖSAd}Sܚ Ĝ:1j[kgv&87\UUNScQ+E*i,6kBwv_xDYvLSx5IEWg:Xʔ)I4I*340lnUucE%}vͭHΑhM+*XODŽǬ,(?itK)GXUef~?vE}ӹ5yJZs,4!] Z"ZTa@ ,ĺE~9  A$PxP<3PmA>&&+]RG7N_!g#awMٜr8T)ucfzXsbސSbZٵ]76^޳oozO'J2 \ r@QpO)|0ZsjHA(x"x~㔋 $Js!SSovLGdž6~ӆX 3^=x'~ffOhޮDw82 T񶘻vb]p/Ȟg7PK LQrl=hG dragonmantank-cron-expression-65b2d8e/tests/Cron/CronExpressionTest.phpUTU_is~Ŗ ) !1cFj䱤j*YK؅%A i'۷o|j۳ :vPFhyr cܱ$?<\Kt\z [?;v-ӘޒNV,dw.丏cL`wc E禾B'Γe%3شѝ[0-L)Jr"̈mP"2B\r3α%h<]yg/ѝk\Y |5[&.)2] Pöaz>nv{/?_!ekϟuǦtVCm]̹b.[?b\ bxɨ}0@]UV|W@T]VM@PIcFkFi1]\3 ͧ hua~%QˋUdk}fW~8=*,tX³^.q^xp':A(cUhNXt 9Џ@i tG aV52wfa AW GbE4'|N\Ya4l8ęrә|=k!b a/赯bd\[#HKu V :®uV5L6v uXj*f}RV}!`ͻyZ-SYܤkE&$9cW'0T-/✭_ہc(V01oc_+ftdyvp»[ӲNaOW/m|sTČ@tj( . Md~ )`^/W6 ai2!jXɲ?$8|82N$8Hh-Jr]?& Б<2@c*K"0m"_-m0K PQ" Y,Gq(TTrOJ)PFl1HÜ9b (ix 4C~2ml{} :uM#$J`9qY)ĊLj<"f.5HUThQWb/WqꙔ¬n>u5xL8C.,!?ԳAL޼EK@^Zr5/*UG5p}ם *Wa_-{˜dzA "/H aJW7;@Ev%⨪'>M0bðTJyvm<c8ܔ0Y&e`~$g44|OW2_as$iaRPb@2KJ_QXZ/Q^yY5쏎lwc\c\ );{.劒ڗ&^.vIFR~(i!b&rcs3Qž\ bmmaLd]:In ijqm& 7TzMCGD~ea> <S~!qCZ =in(&7aZv>_WV41 D_ ;y0RƑ>Ɛ;>WϕvZg~Z0袎I ^%dZ$9 p(CDsn̐h1~`lE=߬3k0w dyb(c뚮MCct?T&p>p5EGCYKqOgkCq]߼"ٰ\nk@yf<|YKڜ -iܲ﫨a/ZBuˆ4mBu|K, =p V2i^}(9?}}SM!G䢅Ɯ"zV{"oAܜygIFMk!J Gb 4f'PةM#ވ2$a2ASnӨos18ET'c^ciqV$ g< 6K/ؖWD6@t1`_2|Oi0(cDǵS\7d`yV'`99J(=YlIa43jP#,Q*"}'ebفԕtsdb׏[Wje( \XR"GCHՎ唂oJq[;hr8i#GDxrM@ߙA`LIqrBZ-d3+inQ'(ąz1MPbT5zyj˲ Q5hmWCZ$A5I0XXp/K#_$߯3[<}q;VWrCB'0pNb,4رX =^өx:S]b)VH#ъW&H iMH}tɗD?0F՟#GP*#P)cYFS5{'A໴yeϧvyHHgZRQOlMC~[SM WsWkz_K)o,!B+Tf$i58uGx [{3W /QghVH!xQrMCъB}jæ]QN3Y-ZZ>vw 'KϮ>Wd/0]/)vO=湐S'G 0a \I 䞵p%ۦ2;ڶiiTiiiiaIr

A)Έ5q+rf1~ο웒{QybhW⿵!Wa7J<{S1-!S\$t$Dm)#y!JH˩d\P^rVUB*0΁s(Cزu\'@@h?wMYGAef~,JFۙ*)II '/i1凭sH(_bHă?G KB]~Xc ߈uΓI'loyϣX}"X\%K z()8- V夵Dāg:gLo 93RڃudEXJ^\(OMN_^ind~n#O6Ը2Jbg^~+.lȚxw\/~&WT8>ٿJz.mAݩ&|ƻ40TV.XU )u4%t] > "\%a2( L<x ^oԣ5Oc~D V }q[cΘvXB}~PK LQ;;<H dragonmantank-cron-expression-65b2d8e/tests/Cron/DayOfMonthFieldTest.phpUTU_Uao0_qҐ)1M VĊn`&8jb)9!m4˒{sz6%hjNE*tJee:r^2'z };`U1\}ݪQb,C,So}vOXĝX,>hT9Bk*Gu\B|=cUX%vjSVWy~aC&T;w7q 6&hۑ_Bw&OM9VW0*@ùs1e!_hT!`cDù+! m\\[Lk#n}УDIw#ozKvH/PK LQ.}G dragonmantank-cron-expression-65b2d8e/tests/Cron/DayOfWeekFieldTest.phpUTU_Xmo8_aJ*i$@uׂ@jՖzL␨bZ$J].%/gfy!(RУ\SE%y|?-\A{QBI ҏo;, 4ľ +ᡂ0u䅄2O'_ #/M`x1-U"$(9)QVe^:Gkr#E {T)eDyшR)|| bq#ǡ ؇/JR8!a-AnrQ@X4z[IDؕƻ#]c+-כ\ԻoU䚚ˊ-s_qFu+uV'94g~jůz|sA1 ,+q.=',|:ܝҫ\2! MYlÐ+t.ǰӭe`ιڝ޵W7!cwkrSB!5A$¼_0o8 E!oDde8y!4no =&KRJFh,tkmAddDc#3n laf}:iNx }\wL{kZ\Ef`nimie6JZkfkVK+q*64k~?PK LQg?E dragonmantank-cron-expression-65b2d8e/tests/Cron/FieldFactoryTest.phpUTU_RKO0W̡IE)=( VPX|{PG V[qdK$3.u$-?#j#ey Q3ʊ0S [ .72PT5%wtk Q -= T U/UK= 6$a>At4MXLR@7VVΉU$lEUo/?C̔⩄̨UNEnجuolGHEݓ`*b4s ݘw2ZA*VFmorIr*`CR K{4Ǝw-?W{oCWV-fԀlr55QekQN'J%'`?3_N(w:BcᖍWlkp5%? L5/QT1/ ږm҈d Ď'Vz[GN% ;U z XRq̀)FbND_ PK LQo)E dragonmantank-cron-expression-65b2d8e/tests/Cron/MinutesFieldTest.phpUTU_T]o0}ϯH (.VBS%XIi,N)sBHE&/s\^̢0=#bFY96q=$3z8U/bT’JU}po>#މuS"P,aœtiF,}haQYl`6n wfU =f֐P6- Jܟ(AڼXRk}NfujؾDqj z! ycLD @TQ0$5#T梈R6Hq;lQk[ WԸBdsY s8iO|Q]GِX:KPK LQe&^C C dragonmantank-cron-expression-65b2d8e/tests/Cron/MonthFieldTest.phpUTU_Օk@_q?\ζSFAkM.rw.1VkqG zy^?Q04F"#j{ iZ"NdТzlI$hQHr77?W16Pϵr"$ b: Cʆ<0"4<[3e?ݟҭ)xb4tWo*yB.yV)9e{O&)ȑPH0gn2Elg̙j +Ħ\nwf7QmtbZar ~omoȏi*c_ڐ2:E &0JOF{2O9"dlE%6bWX1Q$t.Z8zp\ùf "tۭa&1K 1;'m3zЫļV&>'~ΔD>w"gg2roK^_wN}d\ҟ\8ohTb;վ0E9 @7\ .8Z.Z;_t! 9/&Vף؂ Xpv#yG)0/yk-*E0sE䥟޲/PK Ό~Noz- dragonmantank-cron-expression-72b6fbf/LICENSEUT \]RK0+F9JhgcipF쮶!h|~|m;3?}e?B Q;u kBjʫ~4 Bqգ_8VMQk@/Q-R\ᄤ`2t ҷH_QOzs6Acs_y;N;EyXO" @wWp1gv&Pw<^w77j$=;L@>CmcSy׆7AG`Nw] }OYͳE FĸpSOcqdo]{B`^(1} WSGZ}+V]{}! 5HoNvkeR[&9 ǰ`%!lZX!Yve;)8,!HDpD%Xdϰľ,WT($U9JR.5R$B`%TF\I%M$Y%Gi3$gU(,IH*`t/Dyy`'1Gp[&|PQDBŖYd@e;خ9A3噒x 1To[Q% d%4 hؑO$ؗF 6%tޔbdPK Ό~NiMg / dragonmantank-cron-expression-72b6fbf/README.mdUT \V{o6_ F ,]ӤCt]4+lXhlI؇e9<0=wghnKJz=Ƣ wWC‰a;WAte5'cB9&IJ7F1%֫K5Wtt":BȶOډN* ˬ,2VlVcgL(O[b`r3J:SO:b N²:4SiBpLETiUPYK:>Oj*!L_tͼeV #a@*2%F6 Up؉,KNT5tT4gW!Z GNRKrPshc<;Џp@3ECFNPP4'sv:2y$)uԄᶺAdb#@Xΐ#2o2,K}k]$"NN.l t@ËQ~ӆCEfSXPW$e_&>CʏHT^ctpee\,TO~Ž103w.(;%Rń朽7k 0Q ҷYVaiWL[-"{EŠ@ya˰DJ͹LnC5 SIff >|Pe J*Eh%LDTN3: $䁅I%R1Uo >N?q78H6vM&d1o5Z iaq8FPRvM  -pi 8ޮsQ=n-=#6d `(ݍ&hEn7TUZ/ Ps)S'ʑL x-nqл݁67ZV|{9m5JXg 1=p 0wb "1b|sb1E*NCaQKl{xJ)n{*_32١ݥCh_FQ~ME-])v{MƵ Wv{+BPθ[N{޽{k4xsBnCo1Fj$ _5hlֵQgM.-oZ[)Xcuݘl[VӶӡKYx&|G%+ev7/EyaێՕ#GL8}HG5NGR^r}ieGGW^Sa|z cnzUN pO1Cz"ylJmgPK Ό~N* dragonmantank-cron-expression-72b6fbf/src/UT \PK Ό~N/ dragonmantank-cron-expression-72b6fbf/src/Cron/UT \PK Ό~N8bjyN@ dragonmantank-cron-expression-72b6fbf/src/Cron/AbstractField.phpUT \NF=_qVJCC}\6l vWDh ΄Xةg¥]g{LU̹ߏ߼]/׽^AVIJ*^oۃ]8e")>+XVh>1GҜ0f!V뜮h$ۅMCE; I p âa Tx"OX_W%)GI\H  3"/!-{ZqqwbۓZz b4|IaauQѤct$$rZ̿ $pRhMxsg)+R.g6Kd(O(Oޑk&I0/jG>Bs%M? 1J![ў. Kh05 ߬pz-B{"uHqN Uon2_. IH 5eH+R,PCD43dl 4g#L-E}H+mO&0Ϯz*GHy=5X4`o0W(̗IaEf²(m'}Wb CVlgڅ.)&P䄋:#lE։cĝA(*iDYR]udq@/6#=ڈ8_ "o|mvvWo쫃WI{@R.=^Nnj5m;mCJ\1h*kg7T GA 9/&*31'Cx 1|. 'ܗWL{QPE0cۊD0`Ih`T''89}\lDo+D-fET&AH )z [E$zt>1~~%:ਢcG+Z8" c_? ;aИհX=?B#7X9 zj9`|Y?_7\cJ2 l&Y%{ZK@6){yKa9p@Y\K0CEQp<[ bA1NŵD#}q%hhðh7 O6O4l\F _#?zԬ \K!:\Hpے:S)e'xgT.FH[4&gDȣ?cڬ@CPkcU2.er:<%#BHi"Iˑ-ԇA1`䶟˨#Q=fAR.M@'`bDŠZЈ>uroY՟VvJab:)x &FG_2vͳP3<0+J+jTmq0DdKG,- O›V~ύkmvxQ>iǙ{[tZeP2Wj=xm6|PҭI{A*RdZC;1pR^<=Qٛ)I YZfeM>ʯj+AhؖE7-zY[lS^.am AIج9>pgT.ZBZh/Q %XĔ޹bޞ5Mr6yqd[ar&f C-kpgK茌ڴOnӺ` X7jrm񷽵tGB稗=TӋwWWIZc4 h*Y15){gwg[2ӊ v-fBd"VBkl%؈}3^\#8H-;_mj m])uD=>`ꆧQ\Pt ߠXBug4x%cg f/_[%v͌:.wf',7b8k|aEV)U߈( N*,A/Gps?PK Ό~NDL ^L f;A dragonmantank-cron-expression-72b6fbf/src/Cron/CronExpression.phpUT \[s۶v$WtmN&s]bg,i0 I)Gv97(ٱcz x>xbQlldtxA#F<{QqFQΒ%{x;Z.+Avs&X9 n9B$H_K&r^-Y&Z_TNxkkl7 Ts@ ZrVD4#1u, $Є#bD䤬!Pa$cX 4 L׭'΀YŅs1#@;$J)焖@8i%3-XtbI?@ +G(b5..󢀾2_ŠH/A ~ t*e(# C|E^;x523hOG>W] 9WGo+ ԑKє\3Z=I,(cm_% mf]JbzhE 8zutLcomm{4=r`g/;ÿt>E߃-bG|KZrJH<gQ&x:',H䥦;2SMa3gP$'J_2AM"d~Bx%tdH: Rz] s&O00X eи"KE#~D.j^@WZVbH;6*X1.6*U4(4BeXBEZ,m&J#wpv H /XO``Ld+Ƶl꜋D 𭟦ڽtCfYESx!#DtmTBJg|!gm]v_'Kgʈ^z[=,6ԠGEH& DD=L"B,EJӦ+P۠mLTe׆U)vYE04پc&^53!$֑'|zڔzdOz6zV/cei+rm){I{|RJͦcv2XDs&V*~ I91!ALZ]JM-6誶?(=;Ft /5e @MŪ(aGEL%5CW)v)m?]]\|l}dpWqNo2}xHiV[ө*3GNTpf4тfsoI2萿˂y"e~ɇNcTn+\~m< R)/D{|jևd;$'o<::9{xb mX} ]hkrJ`k "uF mc0Zxt_3D.xNl˘L&0:P*@o<{PVŭQ5D~Б:rEz o] Ŝ8z85&l4~ӁU}(!?ρFlF@܏]^_a3A74Q>-ÂМjٞΙ3#Q0Πk8C*jܪ N96_bu~$EWܧ Nb7]R" h/!mXM쒕.[ ),q>8#h0ч@u+mڕx_ts#;oC 'żjhC.o~e^؝ׁ̄Gbz= ^H*iV-\H29TBص4}f,C 7+T]gdu!Q5fFt&iFnJȂ xWI+lX\M&piQK Yi~kCsz>%\pu#@ 8,-`o(TK s}t*S96pp/󼄝{kF 2XXtQ.4XXչt.\S!Np5bx7Zbb/Gݣ?02USȞ6EcCKC!-bl.BgœuY<+%hro)%sեs3,xى7;,cYjw~L(eDd[=پܞN:N|2w٨V7[ W/z! JӎK7S0vȗ #qYPCb%Lڽ }+&E]uu#D]&ץ ~% D_7W@q@~$쩨ɗHx2=i>kPtΎxةp6w&eg95P?%// /laĈu! ~e'6_Gju!#V-] o [WVo4`@QW]3~ɑ*V+ҦZS\a%PK Ό~NB dragonmantank-cron-expression-72b6fbf/src/Cron/DayOfMonthField.phpUT \Vmo6_q5Hd;itYlҮh^FmhT2c)zkL0`<>ޏ^n֛ c)qxd6 r~)R>o| WKEqk r '$I䝞vSK8+޹ڰ,ְ f z#̚Cj ]yb`d8B [L LqT2<#m8H?,$<G:vToYs{4f݁Ld+$;!-4J9wo8 \HS \0+<%V+ƝHTe%hFxɳQݩ(9%L4!~wgLx;ٷnB va=pg =ZJ4}Ӎx̍$Ө-Osb#d 7"}ak N$(DPUW,7k{+P-OT%XGϫdL擦l}ԞQTbNxr MpzP\ s*bij7Jwad^ ,x>]_M*gje2UPQ٠R70rxf>!&+[GگkhH-VP}~tYY\`t↷l(nqʪ,,25sg\}  k €! T7,w!< ;Bpe0u7_TMd63%3Rf|827-a..*|4|P/ w^P=Xk#xKOliD=jRH4T*g|zc|h§hs)=E A{J`ovhfTsX=w,?-^{ESE\sQ{ڔ$|TFhۯ94Djj }?/bq3` Z{}'TyZ5c3|܈Pdjͣ/vL3}6tٔzF)X" Vw˫AFqHM OuGplb<߆Bێ[,d]WncyMSɢpQuN)lh7{LԯO_V޲[S-]%+Zo\^hoܦ㝇3KA j6)?PK Ό~NùdA dragonmantank-cron-expression-72b6fbf/src/Cron/DayOfWeekField.phpUT \XkSF_q $ v-Pc`dҔ嵭G]ahf-ݽ{>w{ټ l0:`Պ9C[Kg; N D~4} WZ_o:6S8;nh2oIy-K{tFN fLorF"6lL6'z "}Gj #-$fc1 tqun:!V'Wg;'' pFNI 3y)\f ,9ɹ)s'vH"CYwEķi|1 !JE tnF |"XHe5P.IUIua%q;Ueɔ,S[ph=bdW*Pt\gOV]N^tw9f1zbr J\䂙jLr4m-a[sR>oΨ]mɏJj]³NyptyleiduISSU|a_*[= 3 :L@{Z5BT<'_X:ZP; ddfr~Hï%a & YGX SC-(f=Y40+ə>9G+ + vRyvtuipD_,n4jt&$4xi& ;M6&o"iMap$B<bC9{s_@S|](KIyɴ)T0ux9#69q5U" Ŗ.ra$«dʊ~}*ȼ8b7\]uc#7zwzqE̾68O^3l̑7+D7n͐A\bU9Zk%8UTjʰ.#Q :MP^2yMfLI|&¼ү9iW815^9n ߡ=i0o0>׀.$}'.Dž{YPT}[{ƅ,p"&Kel-4EZE*\MScwr8e.l05_ƥW\m4nT4WObp}=da_Z#972ixyW9Q+,%TfFKcX,nx FDɔg* Z[☝'o'{LYUvHLcOsssʰdT=~2~'{{F $lPK Ό~Nα? dragonmantank-cron-expression-72b6fbf/src/Cron/FieldFactory.phpUT \SMo0 Wp@&[O7u+B\I>Iv.M./ŧG[,Ӹ"oQLoz?E"-_Y 0S5^ي"j!^k+K(EelxɖycgB*j\ 2J-LQ^0TBD!&(tw@P*c۵&z3AT:>x~<]`i`2ʁRcѽvCP(1{*chU 8JGS5[jzH#as;3!8zR X;4Z;BƠkLүfv 0d1óiePdg}eуwTZ/-Bv\ɱ]seC~]RUcl]=*r^Tb+I.Z`C Zq0ԍQV0 n-"S}@1zo f]‚LFo1*ʫ/7Ϻḭ3PK Ό~N%":B = dragonmantank-cron-expression-72b6fbf/src/Cron/HoursField.phpUT \UMs0W,3N@Ӵ@ C4\NG7[Hr@Y $Y}V9Ȗ Xp{^)OZTs_ 7='+ sI|.IJ}#ȋuѺ>w3mz?ʘAPRGWQg|]7T˭ڹaHș(RrY"cbjW )!S>eilq߸EK(c3]jA 8zh>J!S5TODE lGA7^;oPK Ό~N)1*? dragonmantank-cron-expression-72b6fbf/src/Cron/MinutesField.phpUT \UKs0+63~!i$zizk3ֶ I]rPgow%dOϠh EA>AFϊGv֨tʫLRԵ|D݅ڼ!n^z9MMȇ1LWn-`ڬB\$.B36]mȦj[{2]ɼnCݶB;@A;RWQgΠtu-i~U;6cfg:H˼~油 sON}) ?ePK Ό~N"*R= dragonmantank-cron-expression-72b6fbf/src/Cron/MonthField.phpUT \Sn1}W"(4R妒T>]ok#{{eTrf|~w/S<vc#1c0(ne. fA.9Rd a-[Ё6tXqk˸3 X,{<[Mx/\cWFQ$0\S=j8g1dD%= 8 ZǗO=8!̽s+|ʲޔywtrCѭ;\]vd|LƐ*FH;(-89]42Y!"Oq_7-SKі-#0 65&8=Z ytQ1V[݇ &ymO,9|Fy^ e|b#rp{i3ҕwk\'p7u"UЏDH tJ/Y,.,Q{`>zGX@PHy?ﶠɰ5PK Ό~N, dragonmantank-cron-expression-72b6fbf/tests/UT \PK Ό~N1 dragonmantank-cron-expression-72b6fbf/tests/Cron/UT \PK Ό~NOiF dragonmantank-cron-expression-72b6fbf/tests/Cron/AbstractFieldTest.phpUT \XN@}WRB8!JA RQP҇ř+]kwE%7KUZK asfٱ-ʐxǂkJYV$7xwJ1Mp#!_.^P)/s˳˯S?pq=&uhѰ$R>pA=`C@G~< x|tDJ8JO%bZG/ae8cy$9]*6l ۀz0(gkVtds}3ٖ0g}soET6t (Ե1hd5٪m.~Jbtzϙ'pL^Z4->li uq!Yۨm7ݖSAd}Sܚ Ĝ:1j[kgv&87\UUNScQ+E*i,6kBwv_xDYvLSx5IEWg:Xʔ)I4I*340lnUucE%}vͭHΑhM+*XODŽǬ,(?itK)GXUef~?vE}ӹ5yJZs,4!] Z"ZTa@ ,ĺE~9  A$PxP<3PmA>&&+]RG7N_!g#awMٜr8T)ucfzXsbސSbZٵ]76^޳oozO'J2 \ r@QpO)|0ZsjHA(x"x~㔋 $Js!SSovLGdž6~ӆX 3^=x'~ffOhޮDw82 T񶘻vb]p/Ȟg7PK Ό~NNEWhG dragonmantank-cron-expression-72b6fbf/tests/Cron/CronExpressionTest.phpUT \=kSȵ}=Sez80dH &dW`otly{+emӧ7ׄnFЉc[72KχC(5l b33rcIz2`Ͷ'Wlytb^4a!O?Z?sgy` F.[0&&:MzDX3{q ;^Ĕ$g."/X:E;@#@_C}p%֘G44t->}&hzCdC{}޲A`kB+! { zز\l#aQ^_ v~R)gBʀzL/_hEj^ں8}0J%VDwMQh$KCx(>$Vb!H`25j\32hDM =Cw]xn?W@; ts(!ڬ^]| $[݇0[Qa}`QK4{(K'/1C /t\W%Z mlj 1fta83Aq?3ɱ:q3X.&`^yr4{  8 [+bhBbuVGRhe`q]>1q 6:gjyLfqOsx⯎oYE@3g'C1o3i yFcYPVV#3L Hyie7mǤwMd^`A+O6^ Ai2!hXIŁL(|<+` 3@KlR1eN* 0iF}`뿦#rI%Ұ$/y̆8@U5yVhmX.4^"":Z ~fHǯt [.v^C4I@5E\Vr) -"/ࠈ|eg$Tvf,QWb/SG}q"O7_h輐%Qs _3?Ե@Hxֶ0̵ kPAU:9 >kc!;3||E¾1 ɂ20E3Dׅ.IZPՂvp}{'XDVD iC cJ9b G:Ӡ`T0\"[xXAdHSHt!g" <5,'\R2Ҫ| 8'v2prdZ8ԝpM1sVlϕ_5yqg M2I  4smX*Z]uU c +IrOH>Wiq{ilt[O/@'$]'6aP;xW'fb|='scG,q+6t>=l>M7#;+1G` 6f|^-=]%xZBiI}_EE{irk8Fazιobbae']x'Yg7v'A%Eɩyܘn a͓0Ɯ"世V{"oXyoH~ "ᖿTChQ-"| fYd : tSzQ>HEuaruRܱ*aD?cQcAO{q^|i!VJM~r587g\Mm>a2~SnӨos7E·T'Yb^mivGf_t?6K/ؖWD6@t1`ď`鞧`1Dnc>7' l08X E@xRױ7dXS2unxtc?z; #KŮDJ‰w٫X`4u%\,ֵ٘K24V #~jrJj49G_& X uu0ŴvD #ق bi3[e :q8{LS8P`~+Umpڲ 1mJz(>h_"9ߎ\Sȡ U?iI ( jU]&_ ͼz@'!_N~Ś8G϶I&p:qd[mucN\Z53^^b%uD5Z ~53OҰ~EᗀD:'TdMo x f.-@^hޢ9WK*,WWd+Ek巃6%;p8p?ezV .{Ѹ$WhE` Ih syC>|hɌI i;n=R9^\P$~"P_ҴøiohؾiFc"˒%_@k].9dɉZlk{afEΰs2ׁ:yI3/H#PLcm&5PV\X{.] nTlPjۦAvPԦ%=8<5GIE<$WDe9 Sx::cP@*v$s1"Vm$oIj{`_dl|k]FLn)j5oؠ` >Y7^ߕ*b;;; u+ %/Z i`7/VFWB.Mo ~˥MyᏯfZXYT{W%ݡT QyMK2b!&t{r2C{" ͪPp|k"eyɏFrYk2-?I_= DOs܂+6Ŧm6PH8܊qAOD[hSZ_p.Q 6\Mn2 /gdZ~+|]mHI C$I-’By~rrr|+:g*L<D@.<;xc|o6q ^*q'? ;xuI] #`0F8.w.DS{Qk3LM+'; z!ęȆGǻ{^}6q;AdUKn l' ȇ7޵uHHPYbU*$E4S&ڨG)[z A@$(@\gₗx~רy|#'jfe?%PtU|.1JRיrZ6 @(]0ڡ#׃PK Ό~N;;<H dragonmantank-cron-expression-72b6fbf/tests/Cron/DayOfMonthFieldTest.phpUT \Uao0_qҐ)1M VĊn`&8jb)9!m4˒{sz6%hjNE*tJee:r^2'z };`U1\}ݪQb,C,So}vOXĝX,>hT9Bk*Gu\B|=cUX%vjSVWy~aC&T;w7q 6&hۑ_Bw&OM9VW0*@ùs1e!_hT!`cDù+! m\\[Lk#n}УDIw#ozKvH/PK Ό~N0|wG dragonmantank-cron-expression-72b6fbf/tests/Cron/DayOfWeekFieldTest.phpUT \XmoH_Ȏ_HI5U{=V5CH!d!Ew/~yfY8 h |H] i{?VOn\OWvw\<za W8G7;vFIP`S}_!f"HRr\$(d!t0:ptō(dѩq25P@cn)'Kl>(p$if(t1W #LyXcc? +㹈B@ 4ʞLrUBڐ7WKimTMʹ]kh,d*r-!C|^g:G*cq-U*)|!fK-kN%yï4y3&,[ij5bM̳X؜ʞ[`N Y|*:ISQ)b#fc[yJF:IJ2/j]|@DBNi°`ˊy,dUs:33\@(A T1ei"ڈΖlbcgӚi0R$ 'x*H`$)h'IB℉`H\`gQK +؝ է\ԻkZ-gsWr4ڟ\t֓9Z(U_{G-W'5&g̻2d fY IL#p I^>kVuxyl f^mȍ]g%b|/;KCܖi"8\nOR+-ݛMKr@!o AMɢasbCqҝ^;tl݈*F MvoIЈB'1hJ![.ơЍg ڮ{Ԩ;^XG }ڦi^m= qI!;v boZ:joؕ @|l$m~Ɯ֟?PK Ό~N8E dragonmantank-cron-expression-72b6fbf/tests/Cron/FieldFactoryTest.phpUT \Rn0+` MSER#95^ SjdHyA/E˶A"f޼7G[X!4V-Jkg;yBԾuL%V<2>&]7a5T*^e9^T7T0Dְta/!2)i<̟{~ ;[)֒+S$w3jI>IcN^ֆ=\:j-\$2U숺5{͗|j4/w$_|xB). ;t4#"req gWqA7vP~0 r-PÝBLz`\rLPf+v8ڒd>%X^bOnQWlpY[ymG@Yي PK Ό~N9; C dragonmantank-cron-expression-72b6fbf/tests/Cron/HoursFieldTest.phpUT \T]o0}ϯRJvBSJM8j 焄P$8s|1gxjp$+S1Rm*7i&U$lq mRno g+v 0P TkĄ&"%LL)pz>%wtk Q -= T U/UK= 6$a>At4MXLR@7VVΉU$lEUo/?C̔⩄̨UNEnجuolGHEݓ`*b4s ݘw2ZA*VFmorIr*`CR K{4Ǝw-?W{oCWV-fԀlr55QekQN'J%'`?3_N(w:BcᖍWlkp5%? L5/QT1/ ږm҈d Ď'Vz[GN% ;U z XRq̀)FbND_ PK Ό~No)E dragonmantank-cron-expression-72b6fbf/tests/Cron/MinutesFieldTest.phpUT \T]o0}ϯH (.VBS%XIi,N)sBHE&/s\^̢0=#bFY96q=$3z8U/bT’JU}po>#މuS"P,aœtiF,}haQYl`6n wfU =f֐P6- Jܟ(AڼXRk}NfujؾDqj z! ycLD @TQ0$5#T梈R6Hq;lQk[ WԸBdsY s8iO|Q]GِX:KPK Ό~Ne&^C C dragonmantank-cron-expression-72b6fbf/tests/Cron/MonthFieldTest.phpUT \Օk@_q?\ζSFAkM.rw.1VkqG zy^?Q04F"#j{ iZ"NdТzlI$hQHr77?W16Pϵr"$ b: Cʆ<0"4cron-expression/src/Cron/HoursField.phpnu[PK!"*R'}Hcron-expression/src/Cron/MonthField.phpnu[PK!,xMcron-expression/src/Cron/DayOfMonthField.phpnu[PK!α)^cron-expression/src/Cron/FieldFactory.phpnu[PK!dd+dcron-expression/src/Cron/DayOfWeekField.phpnu[PK!)1*){cron-expression/src/Cron/MinutesField.phpnu[PK!37s7s<cron-expression/0e47cd322780c04bf723be752bfa0cd7dc203f45.zipnuIwPK!9E)%s%s<cron-expression/f4e0baa8dc33506e8237fdb86c027af3bb97e316.zipnuIwPK Sk