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