From 5f1d6a35220c8c2bb5d76cdf2586d86409cb768f Mon Sep 17 00:00:00 2001 From: David Matejka Date: Fri, 16 Mar 2018 14:40:35 +0100 Subject: [PATCH] init --- .gitignore | 3 ++ .travis.yml | 17 ++++++++ composer.json | 30 ++++++++++++++ log/.gitkeep | 0 phpstan.neon | 0 src/Clock.php | 91 +++++++++++++++++++++++++++++++++++++++++ src/ClockMock.php | 102 ++++++++++++++++++++++++++++++++++++++++++++++ temp/.gitkeep | 0 8 files changed, 243 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 composer.json create mode 100644 log/.gitkeep create mode 100644 phpstan.neon create mode 100644 src/Clock.php create mode 100644 src/ClockMock.php create mode 100644 temp/.gitkeep diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f21ffc --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/composer.lock +/tests/temp +/vendor diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2a4ed78 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: php + +php: + - 7.1 + +cache: + directories: + - $HOME/.composer/cache + +before_script: + - composer self-update --no-interaction + +jobs: + include: + - stage: PHPStan + install: composer update --prefer-dist + script: vendor/bin/phpstan analyse --configuration phpstan.neon --level 7 src/ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..c61c8f3 --- /dev/null +++ b/composer.json @@ -0,0 +1,30 @@ +{ + "name": "mangoweb/clock", + "type": "library", + "description": "Clock class", + "license": "proprietary", + "version": "0.1", + "require": { + "php": "~7.1" + }, + "require-dev": { + "phpstan/phpstan-shim": "~0.9" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "repositories": [ + { + "type": "path", + "url": "../*" + } + ], + "config": { + "preferred-install": "dist", + "optimize-autoloader": true, + "classmap-authoritative": true, + "bin-compat": "full" + } +} diff --git a/log/.gitkeep b/log/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..e69de29 diff --git a/src/Clock.php b/src/Clock.php new file mode 100644 index 0000000..5600c71 --- /dev/null +++ b/src/Clock.php @@ -0,0 +1,91 @@ +setTimestamp($now->getTimestamp()); // trim microseconds + self::$now = $now; + } + } + + return self::$now; + } + + + public static function today(): DateTimeImmutable + { + return self::now()->setTime(0, 0, 0); + } + + + public static function tomorrow(): DateTimeImmutable + { + return self::addDays(1)->setTime(0, 0, 0); + } + + + public static function addSeconds(int $seconds): DateTimeImmutable + { + if ($seconds < 0) { + $seconds = (int) abs($seconds); + return self::now()->sub(new DateInterval("PT{$seconds}S")); + + } else { + return self::now()->add(new DateInterval("PT{$seconds}S")); + } + } + + + public static function addHours(int $hours): DateTimeImmutable + { + if ($hours < 0) { + $hours = (int) abs($hours); + return self::now()->sub(new DateInterval("PT{$hours}H")); + + } else { + return self::now()->add(new DateInterval("PT{$hours}H")); + } + } + + + public static function addDays(int $days): DateTimeImmutable + { + if ($days < 0) { + $days = (int) abs($days); + return self::now()->sub(new DateInterval("P{$days}D")); + + } else { + return self::now()->add(new DateInterval("P{$days}D")); + } + } + + + /** + * You should use this only in workers + */ + public static function refresh(): void + { + self::$now = null; + } +} diff --git a/src/ClockMock.php b/src/ClockMock.php new file mode 100644 index 0000000..ea95651 --- /dev/null +++ b/src/ClockMock.php @@ -0,0 +1,102 @@ +setTime(0, 0, 0); + } + + + /** + * @param DateTimeImmutable|string $now + */ + public static function mockNow($now): void + { + if (is_string($now)) { + $nowString = $now; + foreach (['c', 'Y-m-d', 'Y-m-d H:i'] as $format) { + $now = DateTimeImmutable::createFromFormat($format, $nowString, new \DateTimeZone('UTC')); + if ($now instanceof DateTimeImmutable) { + break; + } + } + } + + if (!$now instanceof DateTimeImmutable) { + throw new \LogicException(); + } + + Clock::refresh(); + Clock::$nowFactory = function () use ($now): DateTimeImmutable { + return $now; + }; + } + + + /** + * @param DateTimeImmutable|string $now + * @param callable $callback + * @return mixed value return by invoking callback + */ + public static function mockNowScoped($now, callable $callback) + { + $before = self::now(); + + try { + self::mockNow($now); + return $callback(); + + } finally { + self::mockNow($before); + } + } + + + public static function addSeconds(int $seconds): void + { + if ($seconds < 0) { + $seconds = (int) abs($seconds); + self::mockNow(self::now()->sub(new DateInterval("PT{$seconds}S"))); + + } else { + self::mockNow(self::now()->add(new DateInterval("PT{$seconds}S"))); + } + } + + + public static function addHours(int $hours): void + { + if ($hours < 0) { + $hours = (int) abs($hours); + self::mockNow(self::now()->sub(new DateInterval("PT{$hours}H"))); + + } else { + self::mockNow(self::now()->add(new DateInterval("PT{$hours}H"))); + } + } + + + public static function addDays(int $days): void + { + if ($days < 0) { + $days = (int) abs($days); + self::mockNow(self::now()->sub(new DateInterval("P{$days}D"))); + + } else { + self::mockNow(self::now()->add(new DateInterval("P{$days}D"))); + } + } +} diff --git a/temp/.gitkeep b/temp/.gitkeep new file mode 100644 index 0000000..e69de29