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