userver: userver/utils/datetime.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
datetime.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/datetime.hpp
4/// @brief Date and Time related converters
5/// @ingroup userver_universal
6
7#include <chrono>
8#include <cstdint>
9#include <optional>
10#include <stdexcept>
11#include <string>
12
13#include <cctz/civil_time.h>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace utils::datetime {
18/// @snippet utils/datetime/from_string_saturating_test.cpp kRfc3339Format
19inline const std::string kRfc3339Format = "%Y-%m-%dT%H:%M:%E*S%Ez";
20/// @snippet utils/datetime/from_string_saturating_test.cpp kTaximeterFormat
21inline const std::string kTaximeterFormat = "%Y-%m-%dT%H:%M:%E6SZ";
22inline constexpr std::time_t kStartOfTheEpoch = 0;
23/// @snippet utils/datetime/datetime_test.cpp kDefaultDriverTimezone
24inline const std::string kDefaultDriverTimezone = "Europe/Moscow";
25/// @snippet utils/datetime/datetime_test.cpp kDefaultTimezone
26inline const std::string kDefaultTimezone = "UTC";
27/// @snippet utils/datetime/from_string_saturating_test.cpp kDefaultFormat
28inline const std::string kDefaultFormat = "%Y-%m-%dT%H:%M:%E*S%z";
29/// @snippet utils/datetime/from_string_saturating_test.cpp kIsoFormat
30inline const std::string kIsoFormat = "%Y-%m-%dT%H:%M:%SZ";
31
32using timepair_t = std::pair<std::uint8_t, std::uint8_t>;
33
34/// Date/time parsing error
35class DateParseError : public std::runtime_error {
36 public:
37 DateParseError(const std::string& timestring);
38};
39
40/// Timezone information lookup error
41class TimezoneLookupError : public std::runtime_error {
42 public:
43 TimezoneLookupError(const std::string& tzname);
44};
45
46/// @brief std::chrono::system_clock::now() that could be mocked
47///
48/// Returns last time point passed to utils::datetime::MockNowSet(), or
49/// std::chrono::system_clock::now() if the timepoint is not mocked.
50std::chrono::system_clock::time_point Now() noexcept;
51
52/// @brief Returns std::chrono::system_clock::time_point from the start of the
53/// epoch
54std::chrono::system_clock::time_point Epoch() noexcept;
55
56/// @brief std::chrono::steady_clock::now() that could be mocked
57///
58/// Returns last time point passed to utils::datetime::MockNowSet(), or
59/// std::chrono::steady_clock::now() if the timepoint is not mocked.
60///
61/// It is only intended for period-based structures/algorithms testing.
62///
63/// @warning You MUST NOT pass time points received from this function outside
64/// of your own code. Otherwise this will break your service in production.
65std::chrono::steady_clock::time_point SteadyNow() noexcept;
66
67// See the comment to SteadyNow()
68class SteadyClock : public std::chrono::steady_clock {
69 public:
70 using time_point = std::chrono::steady_clock::time_point;
71
72 static time_point now() { return SteadyNow(); }
73};
74
75/// @brief Returns true if the time is in range; works over midnight too
76bool IsTimeBetween(int hour, int min, int hour_from, int min_from, int hour_to,
77 int min_to, bool include_time_to = false) noexcept;
78
79/// @brief Returns time in a string of specified format
80///
81/// @throws utils::datetime::TimezoneLookupError
82///
83/// Example:
84///
85/// @snippet utils/datetime/datetime_test.cpp Timestring C time example
86///
87/// @see kRfc3339Format, kTaximeterFormat, kStartOfTheEpoch,
88/// kDefaultDriverTimezone, kDefaultTimezone, kDefaultFormat, kIsoFormat
89std::string Timestring(std::time_t timestamp,
90 const std::string& timezone = kDefaultTimezone,
91 const std::string& format = kDefaultFormat);
92
93/// @brief Returns time in a string of specified format
94/// @see kRfc3339Format, kTaximeterFormat, kStartOfTheEpoch,
95/// kDefaultDriverTimezone, kDefaultTimezone, kDefaultFormat, kIsoFormat
96std::string LocalTimezoneTimestring(std::time_t timestamp,
97 const std::string& format = kDefaultFormat);
98
99/// @brief Returns time in a string of specified format
100/// @throws utils::datetime::TimezoneLookupError
101///
102/// Example:
103///
104/// @snippet utils/datetime/datetime_test.cpp Timestring example
105/// @see kRfc3339Format, kTaximeterFormat, kStartOfTheEpoch,
106/// kDefaultDriverTimezone, kDefaultTimezone, kDefaultFormat, kIsoFormat
107std::string Timestring(std::chrono::system_clock::time_point tp,
108 const std::string& timezone = kDefaultTimezone,
109 const std::string& format = kDefaultFormat);
110
111/// @brief Returns time in a string of specified format
112/// @see kRfc3339Format, kTaximeterFormat, kStartOfTheEpoch,
113/// kDefaultDriverTimezone, kDefaultTimezone, kDefaultFormat, kIsoFormat
114std::string LocalTimezoneTimestring(std::chrono::system_clock::time_point tp,
115 const std::string& format = kDefaultFormat);
116
117/// @brief Extracts time point from a string of a specified format
118/// @throws utils::datetime::DateParseError
119/// @throws utils::datetime::TimezoneLookupError
120///
121/// Example:
122///
123/// @snippet utils/datetime/datetime_test.cpp Stringtime example
124/// @see kRfc3339Format, kTaximeterFormat, kStartOfTheEpoch,
125/// kDefaultDriverTimezone, kDefaultTimezone, kDefaultFormat, kIsoFormat
126std::chrono::system_clock::time_point Stringtime(
127 const std::string& timestring,
128 const std::string& timezone = kDefaultTimezone,
129 const std::string& format = kDefaultFormat);
130
131/// @brief Extracts time point from a string of a specified format
132/// @throws utils::datetime::DateParseError
133/// @see kRfc3339Format, kTaximeterFormat, kStartOfTheEpoch,
134/// kDefaultDriverTimezone, kDefaultTimezone, kDefaultFormat, kIsoFormat
135std::chrono::system_clock::time_point LocalTimezoneStringtime(
136 const std::string& timestring, const std::string& format = kDefaultFormat);
137
138/// @brief Extracts time point from a string, guessing the format
139/// @throws utils::datetime::DateParseError
140/// @throws utils::datetime::TimezoneLookupError
141///
142/// Example:
143///
144/// @snippet utils/datetime/datetime_test.cpp GuessStringtime example
145std::chrono::system_clock::time_point GuessStringtime(
146 const std::string& timestamp, const std::string& timezone);
147
148/// @brief Extracts time point from a string, guessing the format
149/// @throws utils::datetime::DateParseError
150std::chrono::system_clock::time_point GuessLocalTimezoneStringtime(
151 const std::string& timestamp);
152
153/// @brief Returns optional time in a string of specified format
154///
155/// Example:
156///
157/// @snippet utils/datetime/datetime_test.cpp OptionalStringtime example
158/// @see kRfc3339Format, kTaximeterFormat, kStartOfTheEpoch,
159/// kDefaultDriverTimezone, kDefaultTimezone, kDefaultFormat, kIsoFormat
160std::optional<std::chrono::system_clock::time_point> OptionalStringtime(
161 const std::string& timestring,
162 const std::string& timezone = kDefaultTimezone,
163 const std::string& format = kDefaultFormat);
164
165/// @brief Converts time point to std::time_t
166///
167/// Example:
168///
169/// @snippet utils/datetime/datetime_test.cpp Timestring C time example
170std::time_t Timestamp(std::chrono::system_clock::time_point tp) noexcept;
171
172/// @brief Returned current time as std::time_t; could be mocked
173std::time_t Timestamp() noexcept;
174
175/// @brief Parse day time in hh:mm[:ss] format
176/// @param str day time in format hh:mm[:ss]
177/// @return number of second since start of day
178std::uint32_t ParseDayTime(const std::string& str);
179
180/// @brief Converts absolute time in std::chrono::system_clock::time_point to
181/// a civil time of a particular timezone.
182/// @throws utils::datetime::TimezoneLookupError
183///
184/// Example:
185///
186/// @snippet utils/datetime/datetime_test.cpp Localize example
187cctz::civil_second Localize(const std::chrono::system_clock::time_point& tp,
188 const std::string& timezone);
189
190/// @brief Converts absolute time in std::chrono::system_clock::time_point to
191/// a civil time of a local timezone.
192cctz::civil_second LocalTimezoneLocalize(
193 const std::chrono::system_clock::time_point& tp);
194
195/// @brief Converts a civil time in a specified timezone into an absolute time.
196/// @throws utils::datetime::TimezoneLookupError
197///
198/// Example:
199///
200/// @snippet utils/datetime/datetime_test.cpp Localize example
201std::time_t Unlocalize(const cctz::civil_second& local_tp,
202 const std::string& timezone);
203
204/// @brief Converts a civil time in a local timezone into an absolute time.
205std::time_t LocalTimezoneUnlocalize(const cctz::civil_second& local_tp);
206
207/// @brief Returns string with time in ISO8601 format "YYYY-MM-DDTHH:MM:SS+0000"
208/// @param timestamp unix timestamp
209std::string TimestampToString(std::time_t timestamp);
210
211/// @brief Convert time_point to DotNet ticks
212/// @param time point day time
213/// @return number of 100nanosec intervals between current date and 01/01/0001
214///
215/// Example:
216///
217/// @snippet utils/datetime/datetime_test.cpp TimePointToTicks example
218std::int64_t TimePointToTicks(
219 const std::chrono::system_clock::time_point& tp) noexcept;
220
221/// @brief Convert DotNet ticks to a time point
222std::chrono::system_clock::time_point TicksToTimePoint(
223 std::int64_t ticks) noexcept;
224
225/// @brief Compute (a - b) with a specified duration
226template <class Duration, class Clock>
227double CalcTimeDiff(const std::chrono::time_point<Clock>& a,
228 const std::chrono::time_point<Clock>& b) {
229 const auto duration_a = a.time_since_epoch();
230 const auto duration_b = b.time_since_epoch();
231 return std::chrono::duration_cast<Duration>(duration_a - duration_b).count();
232}
233
234} // namespace utils::datetime
235
236USERVER_NAMESPACE_END