Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
matej21 committed Mar 16, 2018
0 parents commit 5f1d6a3
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/composer.lock
/tests/temp
/vendor
17 changes: 17 additions & 0 deletions .travis.yml
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/
30 changes: 30 additions & 0 deletions composer.json
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 added log/.gitkeep
Empty file.
Empty file added phpstan.neon
Empty file.
91 changes: 91 additions & 0 deletions src/Clock.php
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;
}
}
102 changes: 102 additions & 0 deletions src/ClockMock.php
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 added temp/.gitkeep
Empty file.

0 comments on commit 5f1d6a3

Please sign in to comment.