userver: userver/utils/datetime.hpp Source File
Loading...
Searching...
No Matches
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