libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
datetime.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <chrono>
14#include <ctime>
15#include <promeki/namespace.h>
16#include <promeki/string.h>
17#include <promeki/error.h>
18#include <promeki/result.h>
19#include <promeki/duration.h>
20#include <promeki/datatype.h>
21
22PROMEKI_NAMESPACE_BEGIN
23
24class DataStream;
25
54class DateTime {
55 public:
56 PROMEKI_DATATYPE(DateTime, DataTypeDateTime, 1)
57
58
65 static constexpr int64_t Invalid = INT64_MIN;
66
68 Error writeToStream(DataStream &s) const;
70 template <uint32_t V> static Result<DateTime> readFromStream(DataStream &s);
71
73 constexpr static const char *DefaultFormat = "%F %T";
74
76 using Value = std::chrono::system_clock::time_point;
77
79 static DateTime now() { return DateTime(std::chrono::system_clock::now()); }
80
88 static Result<DateTime> fromString(const String &str) {
89 return fromString(str, DefaultFormat);
90 }
91
100 static Result<DateTime> fromString(const String &str, const char *fmt) {
101 if (str == "invalid") return makeResult(DateTime());
102 std::tm tm = {};
103 tm.tm_isdst = -1;
104 const char *result = strptime(str.cstr(), fmt, &tm);
105 if (result == nullptr) return makeError<DateTime>(Error::ParseFailed);
106 return makeResult(DateTime(tm));
107 }
108
114 static DateTime fromNow(const String &description);
115
122 static String strftime(const std::tm &tm, const char *format = DefaultFormat);
123
125 DateTime() = default;
126
131 DateTime(const Value &val)
132 : _ns(std::chrono::duration_cast<std::chrono::nanoseconds>(val.time_since_epoch()).count()) {}
133
138 DateTime(std::tm val)
139 : _ns(std::chrono::duration_cast<std::chrono::nanoseconds>(
140 std::chrono::system_clock::from_time_t(std::mktime(&val)).time_since_epoch())
141 .count()) {}
142
147 DateTime(time_t val)
148 : _ns(std::chrono::duration_cast<std::chrono::nanoseconds>(
149 std::chrono::system_clock::from_time_t(val).time_since_epoch())
150 .count()) {}
151
153 bool isValid() const { return _ns != Invalid; }
154
162 void invalidate() { _ns = Invalid; }
163
175 Duration operator-(const DateTime &other) const {
176 if (!isValid() || !other.isValid()) return Duration();
177 return Duration::fromNanoseconds(_ns - other._ns);
178 }
179
189 DateTime operator+(const Duration &d) const {
190 DateTime r(*this);
191 r += d;
192 return r;
193 }
194
204 DateTime operator-(const Duration &d) const {
205 DateTime r(*this);
206 r -= d;
207 return r;
208 }
209
218 DateTime &operator+=(const Duration &d) {
219 if (!isValid() || !d.isValid()) {
220 _ns = Invalid;
221 } else {
222 _ns += d.nanoseconds();
223 }
224 return *this;
225 }
226
235 DateTime &operator-=(const Duration &d) {
236 if (!isValid() || !d.isValid()) {
237 _ns = Invalid;
238 } else {
239 _ns -= d.nanoseconds();
240 }
241 return *this;
242 }
243
252 DateTime operator+(double seconds) const {
253 DateTime r(*this);
254 r += seconds;
255 return r;
256 }
257
266 DateTime operator-(double seconds) const {
267 DateTime r(*this);
268 r -= seconds;
269 return r;
270 }
271
280 DateTime &operator+=(double seconds) {
281 if (isValid()) _ns += static_cast<int64_t>(seconds * 1'000'000'000.0);
282 return *this;
283 }
284
293 DateTime &operator-=(double seconds) {
294 if (isValid()) _ns -= static_cast<int64_t>(seconds * 1'000'000'000.0);
295 return *this;
296 }
297
299 bool operator==(const DateTime &other) const { return _ns == other._ns; }
300
302 bool operator!=(const DateTime &other) const { return _ns != other._ns; }
303
305 bool operator<(const DateTime &other) const { return _ns < other._ns; }
306
308 bool operator<=(const DateTime &other) const { return _ns <= other._ns; }
309
311 bool operator>(const DateTime &other) const { return _ns > other._ns; }
312
314 bool operator>=(const DateTime &other) const { return _ns >= other._ns; }
315
325 String toString(const char *format = DefaultFormat) const;
326
328 operator String() const { return toString(); }
329
337 time_t toTimeT() const {
338 if (!isValid()) return 0;
339 return std::chrono::system_clock::to_time_t(value());
340 }
341
349 double toDouble() const {
350 if (!isValid()) return 0.0;
351 return static_cast<double>(_ns) / 1'000'000'000.0;
352 }
353
363 int64_t nanoseconds() const { return _ns; }
364
375 Value value() const {
376 return Value(std::chrono::duration_cast<std::chrono::system_clock::duration>(
377 std::chrono::nanoseconds(_ns)));
378 }
379
380 private:
381 int64_t _ns = Invalid;
382};
383
384
385PROMEKI_NAMESPACE_END
386
387PROMEKI_FORMAT_VIA_TOSTRING(promeki::DateTime);
388
389#endif // PROMEKI_ENABLE_CORE