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