-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5f1d6a3
Showing
8 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/composer.lock | ||
/tests/temp | ||
/vendor |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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/ |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} | ||
} |
Empty file.
Empty file.
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Mangoweb\Clock; | ||
|
||
use DateInterval; | ||
use DateTimeImmutable; | ||
use DateTimeZone; | ||
|
||
|
||
class Clock | ||
{ | ||
/** @var null|callable */ | ||
public static $nowFactory; | ||
|
||
/** @var null|DateTimeImmutable */ | ||
private static $now; | ||
|
||
|
||
public static function now(): DateTimeImmutable | ||
{ | ||
if (self::$now === null) { | ||
if (self::$nowFactory !== null) { | ||
self::$now = (self::$nowFactory)(); | ||
|
||
} else { | ||
$now = new DateTimeImmutable('now', new DateTimeZone('UTC')); | ||
$now->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; | ||
} | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Mangoweb\Clock; | ||
|
||
use DateInterval; | ||
use DateTimeImmutable; | ||
|
||
|
||
class ClockMock | ||
{ | ||
public static function now(): DateTimeImmutable | ||
{ | ||
return Clock::now(); | ||
} | ||
|
||
|
||
public static function today(): DateTimeImmutable | ||
{ | ||
return self::now()->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"))); | ||
} | ||
} | ||
} |
Empty file.