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

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

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