11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
22PROMEKI_NAMESPACE_BEGIN
56 PROMEKI_DATATYPE(DateTime, DataTypeDateTime, 1)
65 static constexpr int64_t Invalid = INT64_MIN;
68 Error writeToStream(DataStream &s) const;
70 template <uint32_t V> static Result<DateTime> readFromStream(DataStream &s);
73 constexpr static const
char *DefaultFormat = "%F %T";
76 using Value = std::chrono::system_clock::time_point;
79 static DateTime now() {
return DateTime(std::chrono::system_clock::now()); }
88 static Result<DateTime> fromString(
const String &str) {
89 return fromString(str, DefaultFormat);
100 static Result<DateTime> fromString(
const String &str,
const char *fmt) {
101 if (str ==
"invalid")
return makeResult(DateTime());
104 const char *result = strptime(str.cstr(), fmt, &tm);
105 if (result ==
nullptr)
return makeError<DateTime>(Error::ParseFailed);
106 return makeResult(DateTime(tm));
114 static DateTime fromNow(
const String &description);
122 static String strftime(
const std::tm &tm,
const char *format = DefaultFormat);
125 DateTime() =
default;
131 DateTime(
const Value &val)
132 : _ns(std::chrono::duration_cast<std::chrono::nanoseconds>(val.time_since_epoch()).count()) {}
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())
148 : _ns(std::chrono::duration_cast<std::chrono::nanoseconds>(
149 std::chrono::system_clock::from_time_t(val).time_since_epoch())
153 bool isValid()
const {
return _ns != Invalid; }
162 void invalidate() { _ns = Invalid; }
175 Duration operator-(
const DateTime &other)
const {
176 if (!isValid() || !other.isValid())
return Duration();
177 return Duration::fromNanoseconds(_ns - other._ns);
189 DateTime operator+(
const Duration &d)
const {
204 DateTime operator-(
const Duration &d)
const {
218 DateTime &operator+=(
const Duration &d) {
219 if (!isValid() || !d.isValid()) {
222 _ns += d.nanoseconds();
235 DateTime &operator-=(
const Duration &d) {
236 if (!isValid() || !d.isValid()) {
239 _ns -= d.nanoseconds();
252 DateTime operator+(
double seconds)
const {
266 DateTime operator-(
double seconds)
const {
280 DateTime &operator+=(
double seconds) {
281 if (isValid()) _ns +=
static_cast<int64_t
>(seconds * 1'000'000'000.0);
293 DateTime &operator-=(
double seconds) {
294 if (isValid()) _ns -=
static_cast<int64_t
>(seconds * 1'000'000'000.0);
299 bool operator==(
const DateTime &other)
const {
return _ns == other._ns; }
302 bool operator!=(
const DateTime &other)
const {
return _ns != other._ns; }
305 bool operator<(
const DateTime &other)
const {
return _ns < other._ns; }
308 bool operator<=(
const DateTime &other)
const {
return _ns <= other._ns; }
311 bool operator>(
const DateTime &other)
const {
return _ns > other._ns; }
314 bool operator>=(
const DateTime &other)
const {
return _ns >= other._ns; }
325 String toString(
const char *format = DefaultFormat)
const;
328 operator String()
const {
return toString(); }
337 time_t toTimeT()
const {
338 if (!isValid())
return 0;
339 return std::chrono::system_clock::to_time_t(value());
349 double toDouble()
const {
350 if (!isValid())
return 0.0;
351 return static_cast<double>(_ns) / 1'000'000'000.0;
363 int64_t nanoseconds()
const {
return _ns; }
375 Value value()
const {
376 return Value(std::chrono::duration_cast<std::chrono::system_clock::duration>(
377 std::chrono::nanoseconds(_ns)));
381 int64_t _ns = Invalid;
387PROMEKI_FORMAT_VIA_TOSTRING(promeki::DateTime);