userver: userver/utils/datetime/date.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
date.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/datetime/date.hpp
4/// @brief @copybrief utils::datetime::Date
5
6#include <chrono>
7#include <iosfwd>
8#include <stdexcept>
9#include <string>
10
11#include <userver/compiler/impl/three_way_comparison.hpp>
12#include <userver/formats/common/meta.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace logging {
17class LogHelper;
18}
19
20/// Date and time utilities
21namespace utils::datetime {
22
23/// @ingroup userver_universal userver_containers
24///
25/// @brief Date in format YYYY-MM-DD, std::chrono::year_month_day like type.
26///
27/// Convertible to std::sys_days and could be constructed from year,
28/// month and day integers.
29class Date final {
30public:
31 using Days = std::chrono::duration<long long, std::ratio<86400>>;
32 using SysDays = std::chrono::time_point<std::chrono::system_clock, Days>;
33
34 Date() = default;
35 Date(const Date&) noexcept = default;
36 Date& operator=(const Date&) noexcept = default;
37
38 /// @brief Constructs Date without validation of input arguments
39 Date(int year, int month, int day);
40
41 /// @brief constructor from system clock time point in days.
42 constexpr Date(SysDays tp) noexcept : sys_days_(tp) {}
43
44 /// @brief Returns a time point corresponding to the date.
45 ///
46 /// This function may return the same time point, that was passed to
47 /// constructor.
48 constexpr SysDays GetSysDays() const { return sys_days_; }
49
50 /// @copydoc GetSysDays()
51 constexpr explicit operator SysDays() const { return sys_days_; }
52
53#ifdef USERVER_IMPL_HAS_THREE_WAY_COMPARISON
54 constexpr auto operator<=>(const Date&) const = default;
55#else
56 constexpr bool operator==(Date other) const { return sys_days_ == other.sys_days_; }
57 constexpr bool operator!=(Date other) const { return !(*this == other); }
58 constexpr bool operator<(Date other) const { return sys_days_ < other.sys_days_; }
59 constexpr bool operator<=(Date other) const { return sys_days_ <= other.sys_days_; }
60 constexpr bool operator>(Date other) const { return sys_days_ > other.sys_days_; }
61 constexpr bool operator>=(Date other) const { return sys_days_ >= other.sys_days_; }
62#endif
63
64private:
65 SysDays sys_days_{};
66};
67
68/// Validates date_string and constructs date from YYYY-MM-DD string and
69Date DateFromRFC3339String(const std::string& date_string);
70
71/// Outputs date as a YYYY-MM-DD string
72std::string ToString(Date date);
73
74template <typename Value>
75std::enable_if_t<formats::common::kIsFormatValue<Value>, Date> Parse(const Value& value, formats::parse::To<Date>) {
76 std::string str;
77 try {
78 str = value.template As<std::string>();
79 } catch (const std::exception& e) {
80 throw typename Value::ParseException("Only strings can be parsed as `utils::datetime::Date`");
81 }
82
83 try {
85 } catch (const std::exception& e) {
86 throw typename Value::ParseException("'" + str + "' cannot be parsed to `utils::datetime::Date`");
87 }
88}
89
90template <typename Value>
91std::enable_if_t<formats::common::kIsFormatValue<Value>, Value> Serialize(Date date, formats::serialize::To<Value>) {
92 return typename Value::Builder(ToString(date)).ExtractValue();
93}
94
95template <typename StringBuilder>
96void WriteToStream(Date value, StringBuilder& sw) {
97 WriteToStream(ToString(value), sw);
98}
99
100template <typename LogHelper = USERVER_NAMESPACE::logging::LogHelper>
101USERVER_NAMESPACE::logging::LogHelper& operator<<(USERVER_NAMESPACE::logging::LogHelper& lh, const Date& date) {
102 static_assert(
103 std::is_same_v<LogHelper, USERVER_NAMESPACE::logging::LogHelper>,
104 "This was made template to work well with forward declared "
105 "logging::LogHelper"
106 );
107 return static_cast<LogHelper&>(lh) << ToString(date);
108}
109
110std::ostream& operator<<(std::ostream& os, Date date);
111
112} // namespace utils::datetime
113
114USERVER_NAMESPACE_END