Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CORE_UTILS_SPTIME_H_
25 : #define STAPPLER_CORE_UTILS_SPTIME_H_
26 :
27 : #include "SPStringView.h"
28 :
29 : #define SP_COMPILE_TIME (STAPPLER_VERSIONIZED_NAMESPACE::Time::fromCompileTime(__DATE__, __TIME__))
30 :
31 : namespace STAPPLER_VERSIONIZED stappler {
32 :
33 : class Time;
34 :
35 : struct sp_time_exp_t {
36 : enum tm_gmt_e {
37 : gmt_unset,
38 : gmt_local,
39 : gmt_set,
40 : };
41 :
42 : int32_t tm_usec; /** microseconds past tm_sec */
43 : int32_t tm_sec; /** (0-61) seconds past tm_min */
44 : int32_t tm_min; /** (0-59) minutes past tm_hour */
45 : int32_t tm_hour; /** (0-23) hours past midnight */
46 : int32_t tm_mday; /** (1-31) day of the month */
47 : int32_t tm_mon; /** (0-11) month of the year */
48 : int32_t tm_year; /** year since 1900 */
49 : int32_t tm_wday; /** (0-6) days since Sunday */
50 : int32_t tm_yday; /** (0-365) days since January 1 */
51 : int32_t tm_isdst; /** daylight saving time */
52 : int32_t tm_gmtoff; /** seconds east of UTC */
53 : tm_gmt_e tm_gmt_type = gmt_unset;
54 :
55 : sp_time_exp_t();
56 : sp_time_exp_t(int64_t t, int32_t offset, bool use_localtime);
57 : sp_time_exp_t(int64_t t, int32_t offs);
58 : sp_time_exp_t(int64_t t);
59 : sp_time_exp_t(int64_t t, bool use_localtime);
60 :
61 : sp_time_exp_t(Time t, int32_t offset, bool use_localtime);
62 : sp_time_exp_t(Time t, int32_t offs);
63 : sp_time_exp_t(Time t);
64 : sp_time_exp_t(Time t, bool use_localtime);
65 :
66 : /*
67 : * Parses an HTTP date in one of three standard forms:
68 : *
69 : * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
70 : * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
71 : * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
72 : * 2011-04-28T06:34:00+09:00 ; Atom time format
73 : */
74 : bool read(StringView);
75 :
76 : Time get() const;
77 : Time gmt_get() const;
78 : Time ltz_get() const;
79 :
80 : int64_t geti() const;
81 : int64_t gmt_geti() const;
82 : int64_t ltz_geti() const;
83 :
84 : size_t encodeRfc822(char *) const;
85 : size_t encodeCTime(char *) const;
86 : size_t encodeIso8601(char *, size_t precision) const;
87 : };
88 :
89 : class TimeStorage {
90 : public:
91 : uint64_t toMicroseconds() const;
92 : uint64_t toMilliseconds() const;
93 : uint64_t toSeconds() const;
94 : float toFloatSeconds() const;
95 :
96 595225 : uint64_t toMicros() const { return toMicroseconds(); }
97 : uint64_t toMillis() const { return toMilliseconds(); }
98 :
99 336 : uint64_t mksec() const { return toMicroseconds(); }
100 : uint64_t msec() const { return toMilliseconds(); }
101 0 : uint64_t sec() const { return toSeconds(); }
102 : float fsec() const { return toFloatSeconds(); }
103 :
104 : struct tm asLocal() const;
105 : struct tm asGmt() const;
106 :
107 25 : void setMicros(uint64_t value) { setMicroseconds(value); }
108 25 : void setMillis(uint64_t value) { setMilliseconds(value); }
109 :
110 : void setMicroseconds(uint64_t);
111 : void setMilliseconds(uint64_t);
112 : void setSeconds(time_t);
113 :
114 : void clear();
115 :
116 95252 : constexpr explicit operator bool () const noexcept { return _value != 0; }
117 :
118 175 : TimeStorage() = default;
119 : TimeStorage(const TimeStorage &) = default;
120 : TimeStorage(TimeStorage &&) = default;
121 : TimeStorage & operator= (const TimeStorage &) = default;
122 : TimeStorage & operator= (TimeStorage &&) = default;
123 :
124 1783747 : constexpr TimeStorage(uint64_t v) : _value(v) { }
125 :
126 : protected:
127 : uint64_t _value = 0;
128 : };
129 :
130 : class TimeInterval : public TimeStorage {
131 : public:
132 : static TimeInterval between(const Time &, const Time &);
133 :
134 466278 : constexpr static TimeInterval microseconds(uint64_t mksec) {
135 466278 : return TimeInterval(mksec);
136 : }
137 336 : constexpr static TimeInterval milliseconds(uint64_t msec) {
138 336 : return TimeInterval(msec * 1000ULL);
139 : }
140 7131 : constexpr static TimeInterval seconds(time_t sec) {
141 7131 : return TimeInterval(sec * 1000000ULL);
142 : }
143 2 : constexpr static TimeInterval floatSeconds(float sec) {
144 2 : return TimeInterval(uint64_t(sec * 1000000.0f));
145 : }
146 :
147 : inline const Time operator+(const Time& v) const;
148 :
149 : inline const TimeInterval operator+(const TimeInterval& v) const;
150 : inline TimeInterval& operator+=(const TimeInterval& v);
151 :
152 : inline const TimeInterval operator-(const TimeInterval& v) const;
153 : inline TimeInterval& operator-=(const TimeInterval& v);
154 :
155 : inline const TimeInterval operator*(float s) const;
156 : inline TimeInterval& operator*=(float s);
157 :
158 : inline const TimeInterval operator/(float s) const;
159 : inline TimeInterval& operator/=(float s);
160 :
161 : inline bool operator<(const TimeInterval& v) const;
162 : inline bool operator>(const TimeInterval& v) const;
163 : inline bool operator<=(const TimeInterval& v) const;
164 : inline bool operator>=(const TimeInterval& v) const;
165 : inline bool operator==(const TimeInterval& v) const;
166 : inline bool operator!=(const TimeInterval& v) const;
167 :
168 : TimeInterval(nullptr_t);
169 : TimeInterval & operator= (nullptr_t);
170 :
171 2806 : constexpr TimeInterval() : TimeStorage(0) { }
172 561280 : constexpr TimeInterval(const TimeInterval &other) : TimeStorage(other._value) { }
173 120 : constexpr TimeInterval(TimeInterval &&other) : TimeStorage(other._value) { }
174 1128 : constexpr TimeInterval & operator= (const TimeInterval &other) { _value = other._value; return *this; }
175 966 : constexpr TimeInterval & operator= (TimeInterval &&other) { _value = other._value; return *this; }
176 :
177 : protected:
178 : friend class Time;
179 :
180 : using TimeStorage::TimeStorage;
181 : };
182 :
183 : class Time : public TimeStorage {
184 : public:
185 : static Time now();
186 :
187 : static Time fromCompileTime(const char *, const char *);
188 :
189 : /*
190 : * Parses an HTTP date in one of three standard forms:
191 : *
192 : * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
193 : * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
194 : * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
195 : * 2011-04-28T06:34:00+09:00 ; Atom time format
196 : */
197 : static Time fromHttp(StringView);
198 :
199 : static Time microseconds(uint64_t mksec);
200 : static Time milliseconds(uint64_t msec);
201 : static Time seconds(time_t sec);
202 : static Time floatSeconds(float sec);
203 :
204 : template <typename Interface>
205 1450 : auto toHttp() const -> typename Interface::StringType {
206 1450 : return toRfc822<Interface>();
207 : }
208 :
209 : template <typename Interface>
210 : auto toAtomXml() const -> typename Interface::StringType {
211 : return toIso8601<Interface>(0);
212 : }
213 :
214 : template <typename Interface>
215 1450 : auto toRfc822() const -> typename Interface::StringType {
216 1450 : sp_time_exp_t xt(*this);
217 1450 : char buf[30] = { 0 };
218 1450 : return typename Interface::StringType(buf, xt.encodeRfc822(buf));
219 : }
220 :
221 : template <typename Interface>
222 275 : auto toCTime() const -> typename Interface::StringType {
223 275 : sp_time_exp_t xt(*this, true);
224 275 : char buf[25] = { 0 };
225 275 : return typename Interface::StringType(buf, xt.encodeCTime(buf));
226 : }
227 :
228 : // ISO 8601 dateTime format, used by XML/Atom
229 : // - YYYY-MM-DDThh:mm:ss[.sss]
230 : // precision defined as digit after decimal sep
231 : // min - 0 - no decimal
232 : // 3 - milliseconds precision
233 : // max - 6 - microseconds precision
234 : template <typename Interface>
235 550 : auto toIso8601(size_t precision = 0) const -> typename Interface::StringType {
236 550 : sp_time_exp_t xt(*this, false);
237 550 : char buf[30] = { 0 };
238 550 : return typename Interface::StringType(buf, xt.encodeIso8601(buf, precision));
239 : }
240 :
241 : template <typename Interface>
242 25 : auto toFormat(const char *fmt) const -> typename Interface::StringType {
243 25 : char buf[256] = { 0 }; // should be enough
244 25 : return typename Interface::StringType(buf, encodeToFormat(buf, 256, fmt));
245 : }
246 :
247 : inline const Time operator+(const TimeInterval& v) const;
248 : inline Time& operator+=(const TimeInterval& v);
249 :
250 : inline const TimeInterval operator-(const Time& v) const;
251 : inline const Time operator-(const TimeInterval& v) const;
252 : inline Time& operator-=(const TimeInterval& v);
253 :
254 : inline bool operator<(const Time& v) const;
255 : inline bool operator>(const Time& v) const;
256 : inline bool operator<=(const Time& v) const;
257 : inline bool operator>=(const Time& v) const;
258 : inline bool operator==(const Time& v) const;
259 : inline bool operator!=(const Time& v) const;
260 :
261 : Time(nullptr_t);
262 : Time & operator= (nullptr_t);
263 :
264 33906 : Time() : TimeStorage(0) { }
265 29180 : Time(const Time &other) : TimeStorage(other._value) { }
266 13150 : Time(Time &&other) : TimeStorage(other._value) { }
267 7467 : Time & operator= (const Time &other) { _value = other._value; return *this; }
268 15364 : Time & operator= (Time &&other) { _value = other._value; return *this; }
269 :
270 : size_t encodeToFormat(char *, size_t, const char *fmt) const;
271 :
272 : protected:
273 : friend class TimeInterval;
274 :
275 : using TimeStorage::TimeStorage;
276 : };
277 :
278 5625 : constexpr TimeInterval operator"" _sec ( unsigned long long int val ) { return TimeInterval::seconds((time_t)val); }
279 24 : constexpr TimeInterval operator"" _msec ( unsigned long long int val ) { return TimeInterval::milliseconds(val); }
280 : constexpr TimeInterval operator"" _mksec ( unsigned long long int val ) { return TimeInterval::microseconds(val); }
281 :
282 :
283 : inline const Time TimeInterval::operator+(const Time& v) const {
284 : return v + *this;
285 : }
286 :
287 : inline const TimeInterval TimeInterval::operator+(const TimeInterval& v) const {
288 : return TimeInterval(_value + v._value);
289 : }
290 : inline TimeInterval& TimeInterval::operator+=(const TimeInterval& v) {
291 : _value += v._value;
292 : return *this;
293 : }
294 :
295 47568 : inline const TimeInterval TimeInterval::operator-(const TimeInterval& v) const {
296 47568 : if (_value < v._value) {
297 0 : return TimeInterval();
298 : } else {
299 47568 : return TimeInterval(_value - v._value);
300 : }
301 : }
302 : inline TimeInterval& TimeInterval::operator-=(const TimeInterval& v) {
303 : if (_value < v._value) {
304 : _value = 0;
305 : } else {
306 : _value -= v._value;
307 : }
308 : return *this;
309 : }
310 :
311 : inline const TimeInterval TimeInterval::operator*(float s) const {
312 : return TimeInterval(_value * fabsf(s));
313 : }
314 : inline TimeInterval& TimeInterval::operator*=(float s) {
315 : _value *= fabsf(s);
316 : return *this;
317 : }
318 :
319 : inline const TimeInterval TimeInterval::operator/(float s) const {
320 : return TimeInterval(_value / fabsf(s));
321 : }
322 : inline TimeInterval& TimeInterval::operator/=(float s) {
323 : _value /= fabsf(s);
324 : return *this;
325 : }
326 :
327 774 : inline bool TimeInterval::operator<(const TimeInterval& v) const { return _value < v._value; }
328 59686 : inline bool TimeInterval::operator>(const TimeInterval& v) const { return _value > v._value; }
329 : inline bool TimeInterval::operator<=(const TimeInterval& v) const { return _value <= v._value; }
330 71704 : inline bool TimeInterval::operator>=(const TimeInterval& v) const { return _value >= v._value; }
331 106 : inline bool TimeInterval::operator==(const TimeInterval& v) const { return _value == v._value; }
332 175 : inline bool TimeInterval::operator!=(const TimeInterval& v) const { return _value != v._value; }
333 :
334 2381 : inline const Time Time::operator+(const TimeInterval& v) const {
335 2381 : return Time(_value + v._value);
336 : }
337 : inline Time& Time::operator+=(const TimeInterval& v) {
338 : _value += v._value;
339 : return *this;
340 : }
341 :
342 13814 : inline const TimeInterval Time::operator-(const Time& v) const {
343 13814 : return TimeInterval::between(*this, v);
344 : }
345 583 : inline const Time Time::operator-(const TimeInterval& v) const {
346 583 : if (_value < v._value) {
347 0 : return Time();
348 : }
349 583 : return Time(_value - v._value);
350 : }
351 : inline Time& Time::operator-=(const TimeInterval& v) {
352 : if (_value < v._value) {
353 : _value = 0;
354 : }
355 : _value -= v._value;
356 : return *this;
357 : }
358 :
359 1644 : inline bool Time::operator<(const Time& v) const { return _value < v._value; }
360 11638 : inline bool Time::operator>(const Time& v) const { return _value > v._value; }
361 : inline bool Time::operator<=(const Time& v) const { return _value <= v._value; }
362 : inline bool Time::operator>=(const Time& v) const { return _value >= v._value; }
363 : inline bool Time::operator==(const Time& v) const { return _value == v._value; }
364 375 : inline bool Time::operator!=(const Time& v) const { return _value != v._value; }
365 :
366 : }
367 :
368 : #endif /* STAPPLER_CORE_UTILS_SPTIME_H_ */
|