Completed
Push — master ( 58c1c3...bed08d )
by Andreu
04:34
created

src/UniversalTimestamp.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
4
namespace Litipk\Jiffy;
5
6
7 1
if (!extension_loaded('mongo')) {
8
    trait TsExtension {};
9
} else {
10
    trait TsExtension { use MongoAdapter; };
11
}
12
13
14
/**
15
 * Class UniversalTimestamp
16
 * @package Litipk\Jiffy
17
 */
18
class UniversalTimestamp
19
{
20
    const ISO8601_WITH_MILLISECONDS = '_ISO8601_WITH_MILLIS_';
21
    const ISO8601_WITH_MILLISECONDS_WITHOUT_TZ = '_ISO8601_WITH_MILLIS_WITHOUT_TZ';
22
    const ISO8601_WITH_MICROSECONDS = 'Y-m-d\TH:i:s.uO';
23
    const ISO8601_WITH_MICROSECONDS_WITHOUT_TZ = 'Y-m-d\TH:i:s.u';
24
25
    use TsExtension;
26
27
    /** @var int */
28
    private $millis;
29
30
    /** @var int */
31
    private $micros;
32
33
    /**
34
     * Constructor.
35
     *
36
     * @param integer $millisSinceEpoch
37
     * @param integer $micros
38
     */
39 15
    private function __construct($millisSinceEpoch, $micros = 0)
40
    {
41 15
        if ($millisSinceEpoch < 0 || $micros < 0) {
42 1
            throw new JiffyException('The number of milliseconds and microseconds must be positive');
43
        }
44
45 14
        $this->millis = $millisSinceEpoch + (int)($micros/1000);
46 14
        $this->micros = $micros % 1000;
47 14
    }
48
49
    /**
50
     * @return UniversalTimestamp
51
     */
52 8
    public static function now()
53
    {
54 8
        $ts_parts = explode(' ', microtime());
55
56 8
        return new UniversalTimestamp(
57 8
            (int)floor($ts_parts[0]*1000) + (int)$ts_parts[1]*1000,  // Millis
58 8
            ((int)round($ts_parts[0]*1000000))%1000                  // Micros
59 8
        );
60
    }
61
62
    /**
63
     * @param \DateTimeInterface $dateTime
64
     * @return UniversalTimestamp
65
     */
66 3
    public static function fromDateTimeInterface(\DateTimeInterface $dateTime)
67
    {
68 3
        $dtU = (int)$dateTime->format('u');
69
70 3
        return new UniversalTimestamp(
71 3
            $dateTime->getTimestamp()*1000 + (int)floor($dtU/1000),
72
            $dtU % 1000
73 3
        );
74
    }
75
76
    /**
77
     * @param int $secondsSinceEpoch
78
     * @return UniversalTimestamp
79
     */
80 1
    public static function fromSecondsTimestamp($secondsSinceEpoch)
81
    {
82 1
        return new UniversalTimestamp($secondsSinceEpoch*1000);
83
    }
84
85
    /**
86
     * @param int $millisSinceEpoch
87
     * @param int $micros
88
     * @return UniversalTimestamp
89
     */
90 7
    public static function fromMillisecondsTimestamp($millisSinceEpoch, $micros = 0)
91
    {
92 7
        return new UniversalTimestamp($millisSinceEpoch, $micros);
93
    }
94
95
    /**
96
     * @param mixed $dateObject   If it's an integer, then it's understood as milliseconds since epoch
97
     * @return UniversalTimestamp
98
     */
99 2
    public static function fromWhatever($dateObject) {
100 2
        if (null === $dateObject) {
101 1
            return static::now();
102 2
        } elseif (is_int($dateObject)) {
103 1
            return static::fromMillisecondsTimestamp($dateObject);
104 2
        } elseif ($dateObject instanceof UniversalTimestamp) {
105
            return $dateObject;
106 2
        } elseif ($dateObject instanceof \DateTimeInterface) {
107 1
            return static::fromDateTimeInterface($dateObject);
108 2
        } elseif ($dateObject instanceof \MongoDate) {
109 1
            return static::fromMongoDate($dateObject);
0 ignored issues
show
The method fromMongoDate() does not seem to exist on object<Litipk\Jiffy\UniversalTimestamp>.

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...
110
        } else {
111 1
            throw new JiffyException('The provided value cannot be interpreted as a timestamp');
112
        }
113
    }
114
115
    /**
116
     * @param UniversalTimestamp $otherTimestamp
117
     * @return boolean
118
     */
119 3
    public function isGreaterThan(UniversalTimestamp $otherTimestamp)
120
    {
121
        return (
122 3
            $this->millis > $otherTimestamp->millis ||
123 3
            $this->millis === $otherTimestamp->millis && $this->micros > $otherTimestamp->micros
124 3
        );
125
    }
126
127
    /**
128
     * @param int $seconds
129
     * @return UniversalTimestamp
130
     */
131 1
    public function addSeconds($seconds)
132
    {
133 1
        return new UniversalTimestamp($this->millis + 1000*$seconds, $this->micros);
134
    }
135
136
    /**
137
     * @param int $millis
138
     * @return UniversalTimestamp
139
     */
140 1
    public function addMilliseconds($millis)
141
    {
142 1
        return new UniversalTimestamp($this->millis + $millis, $this->micros);
143
    }
144
145
    /**
146
     * @return int
147
     */
148 9
    public function asSeconds()
149
    {
150 9
        return (int)floor($this->millis/1000);
151
    }
152
153
    /**
154
     * @return int
155
     */
156 6
    public function asMilliseconds()
157
    {
158 6
        return $this->millis;
159
    }
160
161
    /**
162
     * @return int
163
     */
164 1
    public function getRemainingMicroseconds()
165
    {
166 1
        return $this->micros;
167
    }
168
169
    /**
170
     * @param string|\DateTimeZone $tz
171
     * @return \DateTimeImmutable
172
     */
173 2
    public function asDateTimeInterface($tz = 'UTC')
174
    {
175 2
        $dateTime = new \DateTimeImmutable('@'.((string)$this->asSeconds()));
176 2
        $dateTime = $dateTime->setTimezone(is_string($tz) ? new \DateTimeZone($tz) : $tz);
177
178 2
        return new \DateTimeImmutable(
179 2
            $dateTime->format('Y-m-d\TH:i:s').'.'.
180 2
            sprintf("%03d", $this->millis%1000).sprintf("%03d", $this->micros).
181 2
            $dateTime->format('O')
182 2
        );
183
    }
184
185
    /**
186
     * @param string $format
187
     * @param string|\DateTimeZone $tz
188
     * @return string
189
     */
190 2
    public function asFormattedString($format = self::ISO8601_WITH_MICROSECONDS, $tz = 'UTC')
191
    {
192 2
        if (self::ISO8601_WITH_MILLISECONDS === $format) {
193 1
            $rParts = preg_split('/\+/', $this->asDateTimeInterface($tz)->format(\DateTime::ISO8601));
194 1
            return $rParts[0].'.'.((string)$this->millis%1000).'+'.$rParts[1];
195 2
        } elseif (self::ISO8601_WITH_MILLISECONDS_WITHOUT_TZ === $format) {
196 1
            $rParts = preg_split('/\+/', $this->asDateTimeInterface($tz)->format(\DateTime::ISO8601));
197 1
            return $rParts[0].'.'.((string)$this->millis%1000);
198
        } else {
199 2
            return $this->asDateTimeInterface($tz)->format($format);
200
        }
201
    }
202
203
    /**
204
     * @return string
205
     */
206 1
    public function __toString()
207
    {
208 1
        return $this->asFormattedString();
209
    }
210
}
211