blob: 9d5f8bb1044465d95781145750bbc6789dd3e6d6 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento5afbb0b2018-01-01 17:24:18 -05002/*
3 * Copyright (c) 2013-2018 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -080020 */
21
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050022#ifndef NDN_UTIL_TIME_HPP
23#define NDN_UTIL_TIME_HPP
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -080024
Alexander Afanasyev19508852014-01-29 01:01:51 -080025#include "../common.hpp"
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050026
27#include <boost/asio/wait_traits.hpp>
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070028#include <boost/chrono.hpp>
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -080029
30namespace ndn {
Alexander Afanasyevf6468892014-01-29 01:04:14 -080031namespace time {
32
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070033using boost::chrono::duration;
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050034using boost::chrono::duration_cast;
Alexander Afanasyevf6468892014-01-29 01:04:14 -080035
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050036using days = duration<int_fast32_t, boost::ratio<86400>>;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070037using boost::chrono::hours;
38using boost::chrono::minutes;
39using boost::chrono::seconds;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070040using boost::chrono::milliseconds;
41using boost::chrono::microseconds;
42using boost::chrono::nanoseconds;
43
Junxiao Shidc2d6d22016-08-04 14:30:23 +000044/** \return the absolute value of the duration d
45 * \note The function does not participate in the overload resolution
46 * unless std::numeric_limits<Rep>::is_signed is true.
47 */
Davide Pesaventodb4da5e2018-06-15 11:37:52 -040048template<typename Rep, typename Period, typename = std::enable_if_t<std::numeric_limits<Rep>::is_signed>>
Junxiao Shidc2d6d22016-08-04 14:30:23 +000049constexpr duration<Rep, Period>
50abs(duration<Rep, Period> d)
51{
52 return d >= d.zero() ? d : -d;
53}
54
Davide Pesavento0f830802018-01-16 23:58:58 -050055} // namespace time
56
57inline namespace literals {
58inline namespace time_literals {
59
60constexpr time::days
61operator "" _day(unsigned long long days)
62{
63 return time::days{days};
64}
65
66constexpr time::duration<long double, time::days::period>
67operator "" _day(long double days)
68{
69 return time::duration<long double, time::days::period>{days};
70}
71
72constexpr time::days
73operator "" _days(unsigned long long days)
74{
75 return time::days{days};
76}
77
78constexpr time::duration<long double, time::days::period>
79operator "" _days(long double days)
80{
81 return time::duration<long double, time::days::period>{days};
82}
83
84constexpr time::hours
85operator "" _h(unsigned long long hrs)
86{
87 return time::hours{hrs};
88}
89
90constexpr time::duration<long double, time::hours::period>
91operator "" _h(long double hrs)
92{
93 return time::duration<long double, time::hours::period>{hrs};
94}
95
96constexpr time::minutes
97operator "" _min(unsigned long long mins)
98{
99 return time::minutes{mins};
100}
101
102constexpr time::duration<long double, time::minutes::period>
103operator "" _min(long double mins)
104{
105 return time::duration<long double, time::minutes::period>{mins};
106}
107
108constexpr time::seconds
109operator "" _s(unsigned long long secs)
110{
111 return time::seconds{secs};
112}
113
114constexpr time::duration<long double, time::seconds::period>
115operator "" _s(long double secs)
116{
117 return time::duration<long double, time::seconds::period>{secs};
118}
119
120constexpr time::milliseconds
121operator "" _ms(unsigned long long msecs)
122{
123 return time::milliseconds{msecs};
124}
125
126constexpr time::duration<long double, time::milliseconds::period>
127operator "" _ms(long double msecs)
128{
129 return time::duration<long double, time::milliseconds::period>{msecs};
130}
131
132constexpr time::microseconds
133operator "" _us(unsigned long long usecs)
134{
135 return time::microseconds{usecs};
136}
137
138constexpr time::duration<long double, time::microseconds::period>
139operator "" _us(long double usecs)
140{
141 return time::duration<long double, time::microseconds::period>{usecs};
142}
143
144constexpr time::nanoseconds
145operator "" _ns(unsigned long long nsecs)
146{
147 return time::nanoseconds{nsecs};
148}
149
150constexpr time::duration<long double, time::nanoseconds::period>
151operator "" _ns(long double nsecs)
152{
153 return time::duration<long double, time::nanoseconds::period>{nsecs};
154}
155
156} // inline namespace time_literals
157} // inline namespace literals
158
159namespace time {
160
161using namespace literals::time_literals;
162
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700163/**
164 * \brief System clock
165 *
166 * System clock represents the system-wide real time wall clock.
167 *
168 * It may not be monotonic: on most systems, the system time can be
169 * adjusted at any moment. It is the only clock that has the ability
170 * to be displayed and converted to/from UNIX timestamp.
171 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500172 * To get the current time:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700173 *
174 * <code>
175 * system_clock::TimePoint now = system_clock::now();
176 * </code>
177 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500178 * To convert a TimePoint to/from UNIX timestamp:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700179 *
180 * <code>
181 * system_clock::TimePoint time = ...;
182 * uint64_t timestampInMilliseconds = toUnixTimestamp(time).count();
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800183 * system_clock::TimePoint time2 = fromUnixTimestamp(milliseconds(timestampInMilliseconds));
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700184 * </code>
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800185 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800186class system_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800187{
188public:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500189 using duration = boost::chrono::system_clock::duration;
190 using rep = duration::rep;
191 using period = duration::period;
192 using time_point = boost::chrono::time_point<system_clock>;
193 static constexpr bool is_steady = boost::chrono::system_clock::is_steady;
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800194
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700195 typedef time_point TimePoint;
196 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800197
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800198 static time_point
199 now() noexcept;
200
201 static std::time_t
202 to_time_t(const time_point& t) noexcept;
203
204 static time_point
205 from_time_t(std::time_t t) noexcept;
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500206};
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800207
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700208/**
209 * \brief Steady clock
210 *
211 * Steady clock represents a monotonic clock. The time points of this
212 * clock cannot decrease as physical time moves forward. This clock is
213 * not related to wall clock time, and is best suitable for measuring
214 * intervals.
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800215 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800216class steady_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800217{
218public:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500219 using duration = boost::chrono::steady_clock::duration;
220 using rep = duration::rep;
221 using period = duration::period;
222 using time_point = boost::chrono::time_point<steady_clock>;
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800223 static constexpr bool is_steady = true;
224
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700225 typedef time_point TimePoint;
226 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800227
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800228 static time_point
229 now() noexcept;
230
231private:
232 /**
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500233 * \brief Trait function used in detail::SteadyTimer to select proper waiting time
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800234 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500235 * Mock time implementations should return the minimum value to ensure
236 * that Boost.Asio doesn't perform any waiting on mock timers.
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800237 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500238 * @sa http://blog.think-async.com/2007/08/time-travel.html
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800239 */
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500240 static duration
241 to_wait_duration(duration d);
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800242
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500243 friend struct boost::asio::wait_traits<steady_clock>; // see steady-timer.hpp
244};
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800245
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700246/**
247 * \brief Get system_clock::TimePoint representing UNIX time epoch (00:00:00 on Jan 1, 1970)
248 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800249const system_clock::TimePoint&
250getUnixEpoch();
Yingdi Yuf2a82092014-02-03 16:49:15 -0800251
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800252/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700253 * \brief Convert system_clock::TimePoint to UNIX timestamp
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800254 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800255milliseconds
256toUnixTimestamp(const system_clock::TimePoint& point);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800257
258/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700259 * \brief Convert UNIX timestamp to system_clock::TimePoint
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800260 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800261system_clock::TimePoint
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500262fromUnixTimestamp(milliseconds duration);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800263
264/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700265 * \brief Convert to the ISO string representation of the time (YYYYMMDDTHHMMSS,fffffffff)
266 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500267 * If \p timePoint contains doesn't contain fractional seconds,
268 * the output format is YYYYMMDDTHHMMSS
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700269 *
270 * Examples:
271 *
272 * - with fractional nanoseconds: 20020131T100001,123456789
273 * - with fractional microseconds: 20020131T100001,123456
274 * - with fractional milliseconds: 20020131T100001,123
275 * - without fractional seconds: 20020131T100001
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800276 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700277std::string
278toIsoString(const system_clock::TimePoint& timePoint);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800279
280/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700281 * \brief Convert from the ISO string (YYYYMMDDTHHMMSS,fffffffff) representation
282 * to the internal time format
283 *
284 * Examples of accepted ISO strings:
285 *
286 * - with fractional nanoseconds: 20020131T100001,123456789
287 * - with fractional microseconds: 20020131T100001,123456
288 * - with fractional milliseconds: 20020131T100001,123
289 * - without fractional seconds: 20020131T100001
290 *
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800291 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700292system_clock::TimePoint
293fromIsoString(const std::string& isoString);
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700294
295/**
296 * \brief Convert time point to string with specified format
297 *
298 * By default, `%Y-%m-%d %H:%M:%S` is used, producing dates like
299 * `2014-04-10 22:51:00`
300 *
301 * \param timePoint time point of system_clock
302 * \param format desired output format (default: `%Y-%m-%d %H:%M:%S`)
303 * \param locale desired locale (default: "C" locale)
304 *
Davide Pesavento844b0932018-05-07 01:00:16 -0400305 * \sa https://www.boost.org/doc/libs/1_58_0/doc/html/date_time/date_time_io.html#date_time.format_flags
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500306 * describes possible formatting flags
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700307 **/
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700308std::string
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700309toString(const system_clock::TimePoint& timePoint,
310 const std::string& format = "%Y-%m-%d %H:%M:%S",
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700311 const std::locale& locale = std::locale("C"));
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700312
313/**
314 * \brief Convert from string of specified format into time point
315 *
316 * By default, `%Y-%m-%d %H:%M:%S` is used, accepting dates like
317 * `2014-04-10 22:51:00`
318 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500319 * \param timePointStr string representing time point
320 * \param format input output format (default: `%Y-%m-%d %H:%M:%S`)
321 * \param locale input locale (default: "C" locale)
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700322 *
Davide Pesavento844b0932018-05-07 01:00:16 -0400323 * \sa https://www.boost.org/doc/libs/1_58_0/doc/html/date_time/date_time_io.html#date_time.format_flags
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500324 * describes possible formatting flags
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700325 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700326system_clock::TimePoint
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500327fromString(const std::string& timePointStr,
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700328 const std::string& format = "%Y-%m-%d %H:%M:%S",
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700329 const std::locale& locale = std::locale("C"));
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800330
331} // namespace time
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -0800332} // namespace ndn
333
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800334namespace boost {
335namespace chrono {
336
337template<class CharT>
338struct clock_string<ndn::time::system_clock, CharT>
339{
340 static std::basic_string<CharT>
341 since();
342};
343
344template<class CharT>
345struct clock_string<ndn::time::steady_clock, CharT>
346{
347 static std::basic_string<CharT>
348 since();
349};
350
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500351extern template struct clock_string<ndn::time::system_clock, char>;
352extern template struct clock_string<ndn::time::steady_clock, char>;
353
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800354} // namespace chrono
355} // namespace boost
356
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500357#endif // NDN_UTIL_TIME_HPP