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 <stdexcept>
9#include <string>
10
11#include <cctz/civil_time.h>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace utils::datetime {
16/// @ingroup userver_universal userver_constants
17/// @{
18inline const std::string kRfc3339Format = "%Y-%m-%dT%H:%M:%E*S%Ez";
19inline const std::string kTaximeterFormat = "%Y-%m-%dT%H:%M:%E6SZ";
20inline constexpr std::time_t kStartOfTheEpoch = 0;
21inline const std::string kDefaultDriverTimezone = "Europe/Moscow";
22inline const std::string kDefaultTimezone = "UTC";
23inline const std::string kDefaultFormat = "%Y-%m-%dT%H:%M:%E*S%z";
24inline const std::string kIsoFormat = "%Y-%m-%dT%H:%M:%SZ";
25/// @}
26
27using timepair_t = std::pair<uint8_t, uint8_t>;
28
29/// Date/time parsing error
30class DateParseError : public std::runtime_error {
31 public:
32 DateParseError(const std::string& timestring);
33};
34
35/// Timezone information lookup error
36class TimezoneLookupError : public std::runtime_error {
37 public:
38 TimezoneLookupError(const std::string& tzname);
39};
40
41/// @brief std::chrono::system_clock::now() that could be mocked
42std::chrono::system_clock::time_point Now() noexcept;
43
44/// @brief Returns std::chrono::system_clock::time_point from the start of the
45/// epoch
46std::chrono::system_clock::time_point Epoch() noexcept;
47
48/// @brief std::chrono::steady_clock::now() that could be mocked
49///
50/// It is only intended for period-based structures/algorithms testing.
51///
52/// @warning You MUST NOT pass time points received from this function outside
53/// of your own code. Otherwise this will break your service in production.
54std::chrono::steady_clock::time_point SteadyNow() noexcept;
55
56// See the comment to SteadyNow()
57class SteadyClock : public std::chrono::steady_clock {
58 public:
59 using time_point = std::chrono::steady_clock::time_point;
60
61 static time_point now() { return SteadyNow(); }
62};
63
64/// @brief Returns true if the time is in range; works over midnight too
65bool IsTimeBetween(int hour, int min, int hour_from, int min_from, int hour_to,
66 int min_to, bool include_time_to = false) noexcept;
67
68/// @brief Returns time in a string of specified format
69/// @throws utils::datetime::TimezoneLookupError
70std::string Timestring(std::time_t timestamp,
71 const std::string& timezone = kDefaultTimezone,
72 const std::string& format = kDefaultFormat);
73
74/// @brief Returns time in a string of specified format
75std::string LocalTimezoneTimestring(std::time_t timestamp,
76 const std::string& format = kDefaultFormat);
77
78/// @brief Returns time in a string of specified format
79/// @throws utils::datetime::TimezoneLookupError
80std::string Timestring(std::chrono::system_clock::time_point tp,
81 const std::string& timezone = kDefaultTimezone,
82 const std::string& format = kDefaultFormat);
83
84/// @brief Returns time in a string of specified format
85std::string LocalTimezoneTimestring(std::chrono::system_clock::time_point tp,
86 const std::string& format = kDefaultFormat);
87
88/// @brief Extracts time point from a string of a specified format
89/// @throws utils::datetime::DateParseError
90/// @throws utils::datetime::TimezoneLookupError
91std::chrono::system_clock::time_point Stringtime(
92 const std::string& timestring,
93 const std::string& timezone = kDefaultTimezone,
94 const std::string& format = kDefaultFormat);
95
96/// @brief Extracts time point from a string of a specified format
97/// @throws utils::datetime::DateParseError
98std::chrono::system_clock::time_point LocalTimezoneStringtime(
99 const std::string& timestring, const std::string& format = kDefaultFormat);
100
101/// @brief Extracts time point from a string, guessing the format
102/// @throws utils::datetime::DateParseError
103/// @throws utils::datetime::TimezoneLookupError
104std::chrono::system_clock::time_point GuessStringtime(
105 const std::string& timestamp, const std::string& timezone);
106
107/// @brief Extracts time point from a string, guessing the format
108/// @throws utils::datetime::DateParseError
109std::chrono::system_clock::time_point GuessLocalTimezoneStringtime(
110 const std::string& timestamp);
111
112/// @brief Converts time point to std::time_t
113std::time_t Timestamp(std::chrono::system_clock::time_point tp) noexcept;
114
115/// @brief Returned current time as std::time_t; could be mocked
116std::time_t Timestamp() noexcept;
117
118/// @brief Parse day time in hh:mm[:ss] format
119/// @param str day time in format hh:mm[:ss]
120/// @return number of second since start of day
121std::uint32_t ParseDayTime(const std::string& str);
122
123/// @brief Converts absolute time in std::chrono::system_clock::time_point to
124/// a civil time of a particular timezone.
125/// @throws utils::datetime::TimezoneLookupError
126cctz::civil_second Localize(const std::chrono::system_clock::time_point& tp,
127 const std::string& timezone);
128
129/// @brief Converts absolute time in std::chrono::system_clock::time_point to
130/// a civil time of a local timezone.
131cctz::civil_second LocalTimezoneLocalize(
132 const std::chrono::system_clock::time_point& tp);
133
134/// @brief Converts a civil time in a specified timezone into an absolute time.
135/// @throws utils::datetime::TimezoneLookupError
136std::time_t Unlocalize(const cctz::civil_second& local_tp,
137 const std::string& timezone);
138
139/// @brief Converts a civil time in a local timezone into an absolute time.
140std::time_t LocalTimezoneUnlocalize(const cctz::civil_second& local_tp);
141
142/// @brief Returns string with time in ISO8601 format "YYYY-MM-DDTHH:MM:SS+0000"
143/// @param timestamp unix timestamp
144std::string TimestampToString(std::time_t timestamp);
145
146/// @brief Convert time_point to DotNet ticks
147/// @param time point day time
148/// @return number of 100nanosec intervals between current date and 01/01/0001
150 const std::chrono::system_clock::time_point& tp) noexcept;
151
152/// @brief Convert DotNet ticks to a time point
153std::chrono::system_clock::time_point TicksToTimePoint(int64_t ticks) noexcept;
154
155/// @brief Compute (a - b) with a specified duration
156template <class Duration, class Clock>
157double CalcTimeDiff(const std::chrono::time_point<Clock>& a,
158 const std::chrono::time_point<Clock>& b) {
159 const auto duration_a = a.time_since_epoch();
160 const auto duration_b = b.time_since_epoch();
161 return std::chrono::duration_cast<Duration>(duration_a - duration_b).count();
162}
163
164} // namespace utils::datetime
165
166USERVER_NAMESPACE_END