diff --git a/app/code/Magento/Cron/Model/Schedule.php b/app/code/Magento/Cron/Model/Schedule.php index 5670a6867e0fbd71ffd18e025883f411eb834065..39a58ef360cb32afdf854c0516456a780bdfc669 100644 --- a/app/code/Magento/Cron/Model/Schedule.php +++ b/app/code/Magento/Cron/Model/Schedule.php @@ -7,6 +7,8 @@ namespace Magento\Cron\Model; use Magento\Framework\Exception\CronException; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; /** * Crontab schedule model @@ -43,21 +45,29 @@ class Schedule extends \Magento\Framework\Model\AbstractModel const STATUS_ERROR = 'error'; + /** + * @var TimezoneInterface + */ + private $timezoneConverter; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data + * @param TimezoneInterface $timezoneConverter */ public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + TimezoneInterface $timezoneConverter = null ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); + $this->timezoneConverter = $timezoneConverter ?: ObjectManager::getInstance()->get(TimezoneInterface::class); } /** @@ -100,6 +110,9 @@ class Schedule extends \Magento\Framework\Model\AbstractModel return false; } if (!is_numeric($time)) { + //convert time from UTC to admin store timezone + //we assume that all schedules in configuration (crontab.xml and DB tables) are in admin store timezone + $time = $this->timezoneConverter->date($time)->format('Y-m-d H:i'); $time = strtotime($time); } $match = $this->matchCronExpression($e[0], strftime('%M', $time)) diff --git a/app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php b/app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php index 04b47445cc7ba58fa5d97ee4dac9b1dfb89578ec..e9f4c61c7f55146443c32ff99f9a85297a4fb99d 100644 --- a/app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php +++ b/app/code/Magento/Cron/Test/Unit/Model/ScheduleTest.php @@ -13,6 +13,9 @@ use Magento\Cron\Model\Schedule; */ class ScheduleTest extends \PHPUnit\Framework\TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ protected $helper; protected $resourceJobMock; @@ -174,6 +177,35 @@ class ScheduleTest extends \PHPUnit\Framework\TestCase $this->assertEquals($expected, $result); } + public function testTryScheduleWithConversionToAdminStoreTime() + { + $scheduledAt = '2011-12-13 14:15:16'; + $cronExprArr = ['*', '*', '*', '*', '*']; + + // 1. Create mocks + $timezoneConverter = $this->createMock(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class); + $timezoneConverter->expects($this->once()) + ->method('date') + ->with($scheduledAt) + ->willReturn(new \DateTime($scheduledAt)); + + /** @var \Magento\Cron\Model\Schedule $model */ + $model = $this->helper->getObject( + \Magento\Cron\Model\Schedule::class, + ['timezoneConverter' => $timezoneConverter] + ); + + // 2. Set fixtures + $model->setScheduledAt($scheduledAt); + $model->setCronExprArr($cronExprArr); + + // 3. Run tested method + $result = $model->trySchedule(); + + // 4. Compare actual result with expected result + $this->assertTrue($result); + } + /** * @return array */ @@ -187,7 +219,6 @@ class ScheduleTest extends \PHPUnit\Framework\TestCase [$date, [], false], [$date, null, false], [$date, false, false], - [$date, ['*', '*', '*', '*', '*'], true], [strtotime($date), ['*', '*', '*', '*', '*'], true], [strtotime($date), ['15', '*', '*', '*', '*'], true], [strtotime($date), ['*', '14', '*', '*', '*'], true],