Last active
December 7, 2016 03:18
-
-
Save paunin/04ba2a52c273f5312cce7f5c031d28b5 to your computer and use it in GitHub Desktop.
Revisions
-
paunin revised this gist
Dec 7, 2016 . No changes.There are no files selected for viewing
-
paunin revised this gist
Dec 7, 2016 . 1 changed file with 14 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -105,6 +105,19 @@ public function getEndWeekTimestamp(): int { return $this->endWeekTimestamp; } /** * @param int $weekTimestamp * * @return bool */ public function isWithin(int $weekTimestamp):bool { return ( $weekTimestamp >= $this->getStartWeekTimestamp() && $weekTimestamp < $this->getEndWeekTimestamp() ); } } /** @@ -171,8 +184,7 @@ public function getDelay(\DateTime $date): int $i = 1; foreach ($this->intervals as $interval) { if ( // We are in an interval $interval->isWithin($weekTimestamp) ) { return ($interval->getEndWeekTimestamp() - $weekTimestamp) * (-1); } elseif ( // we by passed needed interval @@ -188,8 +200,6 @@ public function getDelay(\DateTime $date): int } $i++; } } } -
paunin revised this gist
Dec 7, 2016 . 1 changed file with 8 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -202,12 +202,14 @@ public function getDelay(\DateTime $date): int new DateTimeZone('Asia/Ho_Chi_minh') ); date_default_timezone_set('Asia/Ho_Chi_minh'); echo $scheduler->getDelay(new \DateTime('Sunday 09:00')).PHP_EOL; // 1 hour to time 1*60*60 = 3600 echo $scheduler->getDelay(new \DateTime('Monday 09:00')).PHP_EOL; // 1 hour to time 1*60*60 = 3600 echo $scheduler->getDelay(new \DateTime('Friday 17:59')).PHP_EOL; // 1 min to the end -60 echo $scheduler->getDelay(new \DateTime('Friday 17:59:59')).PHP_EOL; // 1 sec to the end -1 echo $scheduler->getDelay(new \DateTime('Friday 17:58')).PHP_EOL; // 2 mins to the end -120 echo $scheduler->getDelay(new \DateTime('Saturday 10:00')).PHP_EOL; // 1 day to next week interval 24*60*60 = 86400 echo $scheduler->getDelay(new \DateTime('now')).PHP_EOL; // ? // Check Exceptions::Overlaps in intervals are not allowed -
paunin revised this gist
Dec 7, 2016 . 1 changed file with 129 additions and 36 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,13 +1,62 @@ <?php /** * Class WeekTimestamp */ final class WeekTimestamp { const SECONDS_IN_MINUTE = 60; const SECONDS_IN_HOUR = self::SECONDS_IN_MINUTE * 60; const SECONDS_IN_DAY = self::SECONDS_IN_HOUR * 24; const SECONDS_IN_WEEK = self::SECONDS_IN_DAY * 7; /** * @param DateTime $dateTime * * @return int amount of seconds since the beginning of the week */ public static function createFromDateTime(\DateTime $dateTime): int { return self::create( intval($dateTime->format('w')), intval($dateTime->format('H')), intval($dateTime->format('i')), intval($dateTime->format('s')) ); } /** * @param int $weekDay Day of the week 0 - Sunday, 6 - Saturday * @param int $hour 0-23 * @param int $minute 0-59 * @param int $second 0-59 * * @return int amount of seconds since the beginning of the week */ public static function create( int $weekDay, int $hour = 0, int $minute = 0, int $second = 0 ): int { $timestamp = $weekDay * self::SECONDS_IN_DAY + $hour * self::SECONDS_IN_HOUR + $minute * self::SECONDS_IN_MINUTE + $second; if($timestamp >= self::SECONDS_IN_WEEK){ throw new \RuntimeException('Can\'t create WeekTimestamp'); } return $timestamp; } } /** * Class Interval */ class Interval { private $startWeekTimestamp; private $endWeekTimestamp; @@ -30,20 +79,8 @@ public function __construct( int $endMinute ) { $startWeekTimestamp = WeekTimestamp::create($startDay, $startHour, $startMinute); $endWeekTimestamp = WeekTimestamp::create($endDay, $endHour, $endMinute); if ($startWeekTimestamp >= $endWeekTimestamp) { throw new \RuntimeException('Start of interval should be before end of it'); @@ -68,10 +105,11 @@ public function getEndWeekTimestamp(): int { return $this->endWeekTimestamp; } } /** * Class Scheduler */ class Scheduler { /** @@ -87,7 +125,7 @@ class Scheduler /** * Scheduler constructor. * * @param Interval[] $intervals * @param DateTimeZone $timezone */ public function __construct(array $intervals = [], \DateTimeZone $timezone) @@ -100,10 +138,22 @@ public function __construct(array $intervals = [], \DateTimeZone $timezone) foreach ($intervals as $interval) { $this->intervals[$interval->getStartWeekTimestamp()] = $interval; } // we want to make sure intervals are ordered to be able iterate it from the firs to last ksort($this->intervals); // we need to check overlaps /** @var Interval $previousInterval */ $previousInterval = null; foreach ($this->intervals as $interval) { if ( $previousInterval && $previousInterval->getEndWeekTimestamp() > $interval->getStartWeekTimestamp() ) { throw new \RuntimeException('Overlaps in intervals are not allowed'); } $previousInterval = $interval; } } /** @@ -116,11 +166,7 @@ public function getDelay(\DateTime $date): int { $date->setTimezone($this->timezone); $weekTimestamp = WeekTimestamp::createFromDateTime($date); $i = 1; foreach ($this->intervals as $interval) { @@ -138,7 +184,7 @@ public function getDelay(\DateTime $date): int ) { $timeToFirstInterval = array_values($this->intervals)[0]->getStartWeekTimestamp(); return WeekTimestamp::SECONDS_IN_WEEK - $weekTimestamp + $timeToFirstInterval; } $i++; } @@ -147,6 +193,7 @@ public function getDelay(\DateTime $date): int } } //===================================Tests===================================// $scheduler = new Scheduler( [ new Interval(0, 10, 0, 0, 18, 0), // Sunday 10:00 - Sunday 18:00 - normal interval @@ -155,10 +202,56 @@ public function getDelay(\DateTime $date): int new DateTimeZone('Asia/Ho_Chi_minh') ); echo $scheduler->getDelay(new \DateTime('Sunday 09:00', new DateTimeZone('Asia/Ho_Chi_minh'))).PHP_EOL; // 1 hour to time 1*60*60 = 3600 echo $scheduler->getDelay(new \DateTime('Monday 09:00', new DateTimeZone('Asia/Ho_Chi_minh'))).PHP_EOL; // 1 hour to time 1*60*60 = 3600 echo $scheduler->getDelay(new \DateTime('Friday 17:59', new DateTimeZone('Asia/Ho_Chi_minh'))).PHP_EOL; // 1 min to the end -60 echo $scheduler->getDelay(new \DateTime('Friday 17:59:59', new DateTimeZone('Asia/Ho_Chi_minh'))).PHP_EOL; // 1 sec to the end -1 echo $scheduler->getDelay(new \DateTime('Friday 17:58', new DateTimeZone('Asia/Ho_Chi_minh'))).PHP_EOL; // 2 mins to the end -120 echo $scheduler->getDelay(new \DateTime('Saturday 10:00', new DateTimeZone('Asia/Ho_Chi_minh'))).PHP_EOL; // 1 day to next week interval 24*60*60 = 86400 echo $scheduler->getDelay(new \DateTime('now')).PHP_EOL; // ? // Check Exceptions::Overlaps in intervals are not allowed try { $scheduler = new Scheduler( [ new Interval(0, 10, 0, 0, 18, 0), // Sunday 10:00 - Sunday 18:00 - normal interval new Interval(0, 17, 0, 5, 18, 0), // Sunday 17:00 - Friday 18:00 - over midnight ], new DateTimeZone('Asia/Ho_Chi_minh') ); } catch (\Exception $exception) { echo $exception->getMessage().PHP_EOL; } // Check Exceptions::Overlaps in intervals are not allowed try { $scheduler = new Scheduler( [ ], new DateTimeZone('Asia/Ho_Chi_minh') ); } catch (\Exception $exception) { echo $exception->getMessage().PHP_EOL; } // Check Exceptions::Start of interval should be before end of it try { $scheduler = new Scheduler( [ new Interval(1, 10, 0, 0, 18, 0), // Sunday 10:00 - Sunday 18:00 - normal interval ], new DateTimeZone('Asia/Ho_Chi_minh') ); } catch (\Exception $exception) { echo $exception->getMessage().PHP_EOL; } // Check Exceptions::Can't create WeekTimestamp try { WeekTimestamp::create(8,99,99); } catch (\Exception $exception) { echo $exception->getMessage().PHP_EOL; } -
paunin revised this gist
Dec 6, 2016 . 1 changed file with 0 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -128,12 +128,10 @@ public function getDelay(\DateTime $date): int $weekTimestamp >= $interval->getStartWeekTimestamp() && $weekTimestamp <= $interval->getEndWeekTimestamp() ) { return ($interval->getEndWeekTimestamp() - $weekTimestamp) * (-1); } elseif ( // we by passed needed interval $weekTimestamp < $interval->getStartWeekTimestamp() ) { return $interval->getStartWeekTimestamp() - $weekTimestamp; } elseif ( // Last Interval in the collection, need to get time to the first interval count($this->intervals) == $i -
paunin revised this gist
Dec 6, 2016 . 1 changed file with 0 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -104,8 +104,6 @@ public function __construct(array $intervals = [], \DateTimeZone $timezone) $this->intervals ); // we want to make sure intervals are ordered to be able iterate it from the firs to last // @todo: Need to check that we don't have overlaps } /** @@ -143,7 +141,6 @@ public function getDelay(\DateTime $date): int $timeToFirstInterval = array_values($this->intervals)[0]->getStartWeekTimestamp(); return Interval::SECONDS_IN_WEEK - $weekTimestamp + $timeToFirstInterval; } $i++; } -
paunin revised this gist
Dec 6, 2016 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -165,4 +165,5 @@ public function getDelay(\DateTime $date): int echo $scheduler->getDelay(new \DateTime('Friday 17:59', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 1 min to the end -60 echo $scheduler->getDelay(new \DateTime('Friday 17:59:59', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 1 sec to the end -1 echo $scheduler->getDelay(new \DateTime('Friday 17:58', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 2 mins to the end -120 echo $scheduler->getDelay(new \DateTime('Saturday 10:00', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 1 day to next week interval 24*60*60 = 86400 echo $scheduler->getDelay(new \DateTime('now') . "\n"; // ? -
paunin created this gist
Dec 6, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,168 @@ <?php class Interval { const SECONDS_IN_MINUTE = 60; const SECONDS_IN_HOUR = self::SECONDS_IN_MINUTE * 60; const SECONDS_IN_DAY = self::SECONDS_IN_HOUR * 24; const SECONDS_IN_WEEK = self::SECONDS_IN_DAY * 7; private $startWeekTimestamp; private $endWeekTimestamp; /** * Interval constructor. * * @param int $startDay of the week 0 - Sunday, 6 - Saturday * @param int $startHour 0-23 * @param int $startMinute 0-59 * @param int $endDay of the week 0 - Sunday, 6 - Saturday * @param int $endHour 0-23 * @param int $endMinute 0-59 */ public function __construct( int $startDay, int $startHour, int $startMinute, int $endDay, int $endHour, int $endMinute ) { if ($startDay < 0 || $startDay > 6) { throw new \RuntimeException('Start day should be in interval between 0 and 6'); } if ($endDay < 0 || $endDay > 6) { throw new \RuntimeException('End day should be in interval between 0 and 6'); } $startWeekTimestamp = $startDay * self::SECONDS_IN_DAY + $startHour * self::SECONDS_IN_HOUR + $startMinute * self::SECONDS_IN_MINUTE; $endWeekTimestamp = $endDay * self::SECONDS_IN_DAY + $endHour * self::SECONDS_IN_HOUR + $endMinute * self::SECONDS_IN_MINUTE; if ($startWeekTimestamp >= $endWeekTimestamp) { throw new \RuntimeException('Start of interval should be before end of it'); } $this->startWeekTimestamp = $startWeekTimestamp; $this->endWeekTimestamp = $endWeekTimestamp; } /** * @return int */ public function getStartWeekTimestamp(): int { return $this->startWeekTimestamp; } /** * @return int */ public function getEndWeekTimestamp(): int { return $this->endWeekTimestamp; } } class Scheduler { /** * @var Interval[] */ private $intervals = []; /** * @var \DateTimeZone */ private $timezone; /** * Scheduler constructor. * * @param Interval[] $intervals * @param DateTimeZone $timezone */ public function __construct(array $intervals = [], \DateTimeZone $timezone) { $this->timezone = $timezone; if (!count($intervals)) { throw new \RuntimeException('You should have intervals'); } foreach ($intervals as $interval) { $this->intervals[$interval->getStartWeekTimestamp()] = $interval; } ksort( $this->intervals ); // we want to make sure intervals are ordered to be able iterate it from the firs to last // @todo: Need to check that we don't have overlaps var_dump($this->intervals); } /** * @param DateTime $date * * @return int <=0 amount of seconds to the end of current interval, * >0 - number of seconds to the next interval */ public function getDelay(\DateTime $date): int { $date->setTimezone($this->timezone); $weekTimestamp = intval($date->format('w')) * Interval::SECONDS_IN_DAY + intval($date->format('H')) * Interval::SECONDS_IN_HOUR + intval($date->format('i')) * Interval::SECONDS_IN_MINUTE + intval($date->format('s')); $i = 1; foreach ($this->intervals as $interval) { if ( // We are in an interval $weekTimestamp >= $interval->getStartWeekTimestamp() && $weekTimestamp <= $interval->getEndWeekTimestamp() ) { return ($interval->getEndWeekTimestamp() - $weekTimestamp) * (-1); } elseif ( // we by passed needed interval $weekTimestamp < $interval->getStartWeekTimestamp() ) { return $interval->getStartWeekTimestamp() - $weekTimestamp; } elseif ( // Last Interval in the collection, need to get time to the first interval count($this->intervals) == $i ) { $timeToFirstInterval = array_values($this->intervals)[0]->getStartWeekTimestamp(); return Interval::SECONDS_IN_WEEK - $weekTimestamp + $timeToFirstInterval; } $i++; } return 0; } } $scheduler = new Scheduler( [ new Interval(0, 10, 0, 0, 18, 0), // Sunday 10:00 - Sunday 18:00 - normal interval new Interval(1, 10, 0, 5, 18, 0), // Monday 10:00 - Friday 18:00 - over midnight ], new DateTimeZone('Asia/Ho_Chi_minh') ); echo $scheduler->getDelay(new \DateTime('Sunday 09:00', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 1 hour to time 1*60*60 = 3600 echo $scheduler->getDelay(new \DateTime('Monday 09:00', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 1 hour to time 1*60*60 = 3600 echo $scheduler->getDelay(new \DateTime('Friday 17:59', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 1 min to the end -60 echo $scheduler->getDelay(new \DateTime('Friday 17:59:59', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 1 sec to the end -1 echo $scheduler->getDelay(new \DateTime('Friday 17:58', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 2 mins to the end -120 echo $scheduler->getDelay(new \DateTime('Saturday 10:00', new DateTimeZone('Asia/Ho_Chi_minh'))) . "\n"; // 1 day to next week interval 24*60*60 = 86400