summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/erebos/storage.h15
-rw-r--r--src/storage.cpp41
2 files changed, 56 insertions, 0 deletions
diff --git a/include/erebos/storage.h b/include/erebos/storage.h
index 0859dc8..b6595b6 100644
--- a/include/erebos/storage.h
+++ b/include/erebos/storage.h
@@ -1,6 +1,7 @@
#pragma once
#include <array>
+#include <chrono>
#include <cstring>
#include <filesystem>
#include <memory>
@@ -156,6 +157,18 @@ protected:
Ref(const std::shared_ptr<const Priv> p): PartialRef(p) {}
};
+struct ZonedTime
+{
+ explicit ZonedTime(std::string);
+ ZonedTime(std::chrono::system_clock::time_point t): time(t), zone(0) {}
+ explicit operator std::string() const;
+
+ static ZonedTime now();
+
+ std::chrono::system_clock::time_point time;
+ std::chrono::minutes zone; // zone offset
+};
+
struct UUID
{
explicit UUID(std::string);
@@ -184,6 +197,7 @@ public:
int,
std::string,
std::vector<uint8_t>,
+ ZonedTime,
UUID,
typename S::Ref,
UnknownType> Variant;
@@ -204,6 +218,7 @@ public:
std::optional<int> asInteger() const;
std::optional<std::string> asText() const;
std::optional<std::vector<uint8_t>> asBinary() const;
+ std::optional<ZonedTime> asDate() const;
std::optional<UUID> asUUID() const;
std::optional<typename S::Ref> asRef() const;
std::optional<UnknownType> asUnknown() const;
diff --git a/src/storage.cpp b/src/storage.cpp
index e0819d4..525d83d 100644
--- a/src/storage.cpp
+++ b/src/storage.cpp
@@ -536,6 +536,34 @@ const Storage & Ref::storage() const
}
+ZonedTime::ZonedTime(string str)
+{
+ intmax_t t;
+ unsigned int h, m;
+ char sign[2];
+ if (sscanf(str.c_str(), "%jd %1[+-]%2u%2u", &t, sign, &h, &m) != 4)
+ throw runtime_error("invalid zoned time");
+
+ time = std::chrono::system_clock::time_point(std::chrono::seconds(t));
+ zone = std::chrono::minutes((sign[0] == '-' ? -1 : 1) * (60 * h + m));
+}
+
+ZonedTime::operator string() const
+{
+ char buf[32];
+ unsigned int az = std::chrono::abs(zone).count();
+ snprintf(buf, sizeof(buf), "%jd %c%02u%02u",
+ (intmax_t) std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count(),
+ zone < decltype(zone)::zero() ? '-' : '+', az / 60, az % 60);
+ return string(buf);
+}
+
+ZonedTime ZonedTime::now()
+{
+ return ZonedTime(std::chrono::system_clock::now());
+}
+
+
UUID::UUID(string str)
{
if (uuid_parse(str.c_str(), uuid) != 0)
@@ -591,6 +619,14 @@ optional<vector<uint8_t>> RecordT<S>::Item::asBinary() const
}
template<class S>
+optional<ZonedTime> RecordT<S>::Item::asDate() const
+{
+ if (holds_alternative<ZonedTime>(value))
+ return std::get<ZonedTime>(value);
+ return nullopt;
+}
+
+template<class S>
optional<UUID> RecordT<S>::Item::asUUID() const
{
if (holds_alternative<UUID>(value))
@@ -655,6 +691,8 @@ optional<RecordT<S>> RecordT<S>::decode(const S & st,
items->emplace_back(name, value);
else if (type == "b")
items->emplace_back(name, base64::decode(value));
+ else if (type == "d")
+ items->emplace_back(name, ZonedTime(value));
else if (type == "u")
items->emplace_back(name, UUID(value));
else if (type == "r.b2") {
@@ -736,6 +774,9 @@ vector<uint8_t> RecordT<S>::encodeInner() const
} else if (auto x = item.asBinary()) {
type = "b";
value = base64::encode(*x);
+ } else if (auto x = item.asDate()) {
+ type = "d";
+ value = string(*x);
} else if (auto x = item.asUUID()) {
type = "u";
value = string(*x);