Passed
Push — master ( 33e582...680f77 )
by Mr
02:06
created

Timestamp::isEmpty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
/**
3
 * This file is part of the daikon-cqrs/value-object project.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Daikon\ValueObject;
10
11
use Daikon\Interop\Assertion;
12
use Daikon\Interop\InvalidArgumentException;
13
use Daikon\Interop\MakeEmptyInterface;
14
use DateTimeImmutable;
15
use DateTimeZone;
16
17
final class Timestamp implements MakeEmptyInterface, ValueObjectInterface
18
{
19
    public const NATIVE_FORMAT = 'Y-m-d\TH:i:s.uP';
20
21
    private ?DateTimeImmutable $value;
22
23
    public static function now(): self
24
    {
25
        return new self(new DateTimeImmutable);
26
    }
27
28
    public static function epoch(): self
29
    {
30
        return new self((new DateTimeImmutable)->setTimestamp(0));
0 ignored issues
show
Bug introduced by
It seems like new DateTimeImmutable()->setTimestamp(0) can also be of type false; however, parameter $value of Daikon\ValueObject\Timestamp::__construct() does only seem to accept DateTimeImmutable|null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

30
        return new self(/** @scrutinizer ignore-type */ (new DateTimeImmutable)->setTimestamp(0));
Loading history...
31
    }
32
33
    /** @param int|string $time */
34
    public static function fromTime($time): self
35
    {
36
        Assertion::integerish($time, 'Unix time must be an integer.');
37
        Assertion::greaterOrEqualThan((int)$time, 0, 'Unix time must be greater or equal than 0.');
38
        return new self(new DateTimeImmutable("@$time"));
39
    }
40
41 1
    public static function makeEmpty(): self
42
    {
43 1
        return new self;
44
    }
45
46 1
    public function toTime(): int
47
    {
48 1
        Assertion::false($this->isEmpty(), 'Cannot convert null to time.');
49
        /** @psalm-suppress PossiblyNullReference */
50 1
        return $this->value->getTimestamp();
0 ignored issues
show
Bug introduced by
The method getTimestamp() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

50
        return $this->value->/** @scrutinizer ignore-call */ getTimestamp();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
51
    }
52
53 8
    public static function fromString(string $date, string $format = self::NATIVE_FORMAT): self
54
    {
55 8
        if ($date === 'now') {
56
            return self::now();
57
        }
58
59 8
        if ($date === 'epoch') {
60
            return self::epoch();
61
        }
62
63 8
        if (is_numeric($date)) {
64 1
            $format = strpos($date, '.') ? 'U.u' : 'U';
65
        }
66
67 8
        if (!$dateTime = DateTimeImmutable::createFromFormat($format, $date)) {
68 1
            $time = strtotime($date);
69 1
            if ($time === false || !$dateTime = new DateTimeImmutable('@'.$time)) {
70
                throw new InvalidArgumentException('Invalid date string given to '.self::class);
71
            }
72
        }
73
74 8
        return new self($dateTime);
75
    }
76
77
    /** @param null|string $value */
78 8
    public static function fromNative($value): self
79
    {
80 8
        Assertion::nullOrString($value, 'Trying to create Timestamp VO from unsupported value type.');
81 8
        return empty($value) || $value === 'null' ? new self : self::fromString($value);
82
    }
83
84 6
    public function toNative(): ?string
85
    {
86 6
        return is_null($this->value) ? null : $this->value->format(self::NATIVE_FORMAT);
87
    }
88
89
    /** @param self $comparator */
90 1
    public function equals($comparator): bool
91
    {
92 1
        Assertion::isInstanceOf($comparator, self::class);
93 1
        return $this->toNative() === $comparator->toNative();
94
    }
95
96 5
    public function isEmpty(): bool
97
    {
98 5
        return $this->value === null;
99
    }
100
101 1
    public function isBefore(self $comparand): bool
102
    {
103 1
        if ($this->isEmpty()) {
104 1
            return true;
105 1
        } elseif ($comparand->isEmpty()) {
106 1
            return false;
107
        } else {
108 1
            return $this->value < DateTimeImmutable::createFromFormat(self::NATIVE_FORMAT, (string)$comparand);
109
        }
110
    }
111
112 1
    public function isAfter(self $comparand): bool
113
    {
114 1
        if ($this->isEmpty()) {
115 1
            return false;
116 1
        } elseif ($comparand->isEmpty()) {
117 1
            return true;
118
        } else {
119 1
            return $this->value > DateTimeImmutable::createFromFormat(self::NATIVE_FORMAT, (string)$comparand);
120
        }
121
    }
122
123
    /** @param string $interval */
124 1
    public function modify($interval): self
125
    {
126 1
        Assertion::false($this->isEmpty(), 'Cannot modify null Timestamp.');
127 1
        Assertion::string($interval);
128 1
        Assertion::notEmpty($interval);
129
        /** @psalm-suppress PossiblyNullReference */
130 1
        $modified = $this->value->modify($interval);
131 1
        Assertion::isInstanceOf($modified, DateTimeImmutable::class, 'Invalid modification interval.');
132
133 1
        return new self($modified);
134
    }
135
136 4
    public function __toString(): string
137
    {
138 4
        return $this->toNative() ?? 'null';
139
    }
140
141 8
    private function __construct(DateTimeImmutable $value = null)
142
    {
143 8
        $this->value = $value ? $value->setTimezone(new DateTimeZone('UTC')) : $value;
144 8
    }
145
}
146