12#include <userver/dump/fwd.hpp>
13#include <userver/storages/postgres/io/buffer_io.hpp>
14#include <userver/storages/postgres/io/buffer_io_base.hpp>
15#include <userver/storages/postgres/io/interval.hpp>
16#include <userver/storages/postgres/io/transform_io.hpp>
17#include <userver/storages/postgres/io/type_mapping.hpp>
18#include <userver/utils/strong_typedef.hpp>
20USERVER_NAMESPACE_BEGIN
25struct TimePointTzTag {};
26struct TimePointWithoutTzTag {};
29using ClockType = std::chrono::system_clock;
30using TimePoint = ClockType::time_point;
31using IntervalType = std::chrono::microseconds;
40struct TimePointTz
final :
public USERVER_NAMESPACE::
utils::StrongTypedef<
41 detail::TimePointTzTag,
44 using StrongTypedef::StrongTypedef;
46 operator TimePoint()
const {
return GetUnderlying(); }
40struct TimePointTz
final :
public USERVER_NAMESPACE::
utils::StrongTypedef< {
…};
53std::ostream& operator<<(std::ostream&, TimePointTz);
62struct TimePointWithoutTz
final :
public USERVER_NAMESPACE::
utils::StrongTypedef<
63 detail::TimePointWithoutTzTag,
66 using StrongTypedef::StrongTypedef;
68 operator TimePoint()
const {
return GetUnderlying(); }
62struct TimePointWithoutTz
final :
public USERVER_NAMESPACE::
utils::StrongTypedef< {
…};
75std::ostream& operator<<(std::ostream&, TimePointWithoutTz);
105template <
typename Duration,
typename Buffer>
106void DoFormatTimePoint(std::chrono::time_point<ClockType, Duration> value,
const UserTypes& types, Buffer& buf) {
109 WriteBuffer(types, buf, std::numeric_limits<Bigint>::max());
111 WriteBuffer(types, buf, std::numeric_limits<Bigint>::min());
113 const auto tmp = std::chrono::duration_cast<std::chrono::microseconds>(value - pg_epoch).count();
114 WriteBuffer(types, buf, tmp);
118template <
typename Duration>
119void DoParseTimePoint(std::chrono::time_point<ClockType, Duration>& value,
const FieldBuffer& buffer) {
123 if (usec == std::numeric_limits<Bigint>::max()) {
125 }
else if (usec == std::numeric_limits<Bigint>::min()) {
128 value = pg_epoch + std::chrono::microseconds{usec};
133struct TimePointStrongTypedefFormatter {
136 explicit TimePointStrongTypedefFormatter(T val) : value{val} {}
138 template <
typename Buffer>
139 void operator()(
const UserTypes& types, Buffer& buf)
const {
140 detail::DoFormatTimePoint(value.GetUnderlying(), types, buf);
145struct TimePointStrongTypedefParser : BufferParserBase<T> {
146 using BufferParserBase<T>::BufferParserBase;
148 void operator()(
const FieldBuffer& buffer) { detail::DoParseTimePoint(
this->value.GetUnderlying(), buffer); }
155struct BufferFormatter<TimePointTz> : detail::TimePointStrongTypedefFormatter<TimePointTz> {
156 using TimePointStrongTypedefFormatter::TimePointStrongTypedefFormatter;
155struct BufferFormatter<TimePointTz> : detail::TimePointStrongTypedefFormatter<TimePointTz> {
…};
161struct BufferFormatter<TimePointWithoutTz> : detail::TimePointStrongTypedefFormatter<TimePointWithoutTz> {
162 using TimePointStrongTypedefFormatter::TimePointStrongTypedefFormatter;
161struct BufferFormatter<TimePointWithoutTz> : detail::TimePointStrongTypedefFormatter<TimePointWithoutTz> {
…};
167struct BufferParser<TimePointTz> : detail::TimePointStrongTypedefParser<TimePointTz> {
168 using TimePointStrongTypedefParser::TimePointStrongTypedefParser;
167struct BufferParser<TimePointTz> : detail::TimePointStrongTypedefParser<TimePointTz> {
…};
173struct BufferParser<TimePointWithoutTz> : detail::TimePointStrongTypedefParser<TimePointWithoutTz> {
174 using TimePointStrongTypedefParser::TimePointStrongTypedefParser;
173struct BufferParser<TimePointWithoutTz> : detail::TimePointStrongTypedefParser<TimePointWithoutTz> {
…};
182struct BufferFormatter<TimePoint> {
183 using ValueType = TimePoint;
185 const ValueType value;
187 explicit BufferFormatter(ValueType val) : value{val} {}
189 template <
typename Buffer>
190 void operator()(
const UserTypes& types, Buffer& buf)
const {
191#if !USERVER_POSTGRES_ENABLE_LEGACY_TIMESTAMP
194 "====================> userver: Writing "
195 "std::chrono::system_clock::time_point is not supported. "
196 "Rewrite using the TimePointWithoutTz or TimePointTz types, "
197 "or define USERVER_POSTGRES_ENABLE_LEGACY_TIMESTAMP to 1."
200 detail::DoFormatTimePoint(value, types, buf);
209struct BufferParser<TimePoint> : detail::BufferParserBase<TimePoint> {
210 using BufferParserBase::BufferParserBase;
212 void operator()(
const FieldBuffer& buffer) { detail::DoParseTimePoint(
this->value, buffer); }
209struct BufferParser<TimePoint> : detail::BufferParserBase<TimePoint> {
…};
217template <
typename Rep,
typename Period>
218struct DurationIntervalCvt {
219 using UserType = std::chrono::duration<Rep, Period>;
220 UserType operator()(
const Interval& wire_val)
const {
221 return std::chrono::duration_cast<UserType>(wire_val.GetDuration());
223 Interval operator()(
const UserType& user_val)
const {
224 return Interval{std::chrono::duration_cast<IntervalType>(user_val)};
233template <
typename Rep,
typename Period>
234struct Output<std::chrono::duration<Rep, Period>> {
236 std::chrono::duration<Rep, Period>,
237 io::detail::Interval,
238 io::detail::DurationIntervalCvt<Rep, Period>>;
234struct Output<std::chrono::duration<Rep, Period>> {
…};
242template <
typename Rep,
typename Period>
243struct Input<std::chrono::duration<Rep, Period>> {
245 std::chrono::duration<Rep, Period>,
246 io::detail::Interval,
247 io::detail::DurationIntervalCvt<Rep, Period>>;
243struct Input<std::chrono::duration<Rep, Period>> {
…};
253struct CppToSystemPg<TimePointTz> : PredefinedOid<
PredefinedOids::kTimestamptz> {};
256struct CppToSystemPg<TimePointWithoutTz> : PredefinedOid<
PredefinedOids::kTimestamp> {};
259template <
typename Duration>
260struct CppToSystemPg<std::chrono::time_point<ClockType, Duration>> : PredefinedOid<
PredefinedOids::kTimestamp> {};
262template <
typename Rep,
typename Period>
263struct CppToSystemPg<std::chrono::duration<Rep, Period>> : PredefinedOid<
PredefinedOids::kInterval> {};
287struct std::hash<USERVER_NAMESPACE::storages::
postgres::TimePointTz> {
288 std::size_t operator()(
const USERVER_NAMESPACE::storages::
postgres::TimePointTz& v)
290 return std::hash<USERVER_NAMESPACE::storages::
postgres::TimePoint::duration::rep>{}(
291 v.GetUnderlying().time_since_epoch().count()
287struct std::hash<USERVER_NAMESPACE::storages::
postgres::TimePointTz> {
…};
298struct std::hash<USERVER_NAMESPACE::storages::
postgres::TimePointWithoutTz> {
299 std::size_t operator()(
const USERVER_NAMESPACE::storages::
postgres::TimePointWithoutTz& v)
301 return std::hash<USERVER_NAMESPACE::storages::
postgres::TimePoint::duration::rep>{}(
302 v.GetUnderlying().time_since_epoch().count()
298struct std::hash<USERVER_NAMESPACE::storages::
postgres::TimePointWithoutTz> {
…};