blob: cf497affe8f57420ce92b18de42b32f18d0ca4f2 [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 */
48template<typename Rep, typename Period,
Junxiao Shi5537d132016-08-05 03:48:01 +000049 typename = typename std::enable_if<std::numeric_limits<Rep>::is_signed>::type>
Junxiao Shidc2d6d22016-08-04 14:30:23 +000050constexpr duration<Rep, Period>
51abs(duration<Rep, Period> d)
52{
53 return d >= d.zero() ? d : -d;
54}
55
Davide Pesavento0f830802018-01-16 23:58:58 -050056} // namespace time
57
58inline namespace literals {
59inline namespace time_literals {
60
61constexpr time::days
62operator "" _day(unsigned long long days)
63{
64 return time::days{days};
65}
66
67constexpr time::duration<long double, time::days::period>
68operator "" _day(long double days)
69{
70 return time::duration<long double, time::days::period>{days};
71}
72
73constexpr time::days
74operator "" _days(unsigned long long days)
75{
76 return time::days{days};
77}
78
79constexpr time::duration<long double, time::days::period>
80operator "" _days(long double days)
81{
82 return time::duration<long double, time::days::period>{days};
83}
84
85constexpr time::hours
86operator "" _h(unsigned long long hrs)
87{
88 return time::hours{hrs};
89}
90
91constexpr time::duration<long double, time::hours::period>
92operator "" _h(long double hrs)
93{
94 return time::duration<long double, time::hours::period>{hrs};
95}
96
97constexpr time::minutes
98operator "" _min(unsigned long long mins)
99{
100 return time::minutes{mins};
101}
102
103constexpr time::duration<long double, time::minutes::period>
104operator "" _min(long double mins)
105{
106 return time::duration<long double, time::minutes::period>{mins};
107}
108
109constexpr time::seconds
110operator "" _s(unsigned long long secs)
111{
112 return time::seconds{secs};
113}
114
115constexpr time::duration<long double, time::seconds::period>
116operator "" _s(long double secs)
117{
118 return time::duration<long double, time::seconds::period>{secs};
119}
120
121constexpr time::milliseconds
122operator "" _ms(unsigned long long msecs)
123{
124 return time::milliseconds{msecs};
125}
126
127constexpr time::duration<long double, time::milliseconds::period>
128operator "" _ms(long double msecs)
129{
130 return time::duration<long double, time::milliseconds::period>{msecs};
131}
132
133constexpr time::microseconds
134operator "" _us(unsigned long long usecs)
135{
136 return time::microseconds{usecs};
137}
138
139constexpr time::duration<long double, time::microseconds::period>
140operator "" _us(long double usecs)
141{
142 return time::duration<long double, time::microseconds::period>{usecs};
143}
144
145constexpr time::nanoseconds
146operator "" _ns(unsigned long long nsecs)
147{
148 return time::nanoseconds{nsecs};
149}
150
151constexpr time::duration<long double, time::nanoseconds::period>
152operator "" _ns(long double nsecs)
153{
154 return time::duration<long double, time::nanoseconds::period>{nsecs};
155}
156
157} // inline namespace time_literals
158} // inline namespace literals
159
160namespace time {
161
162using namespace literals::time_literals;
163
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700164/**
165 * \brief System clock
166 *
167 * System clock represents the system-wide real time wall clock.
168 *
169 * It may not be monotonic: on most systems, the system time can be
170 * adjusted at any moment. It is the only clock that has the ability
171 * to be displayed and converted to/from UNIX timestamp.
172 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500173 * To get the current time:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700174 *
175 * <code>
176 * system_clock::TimePoint now = system_clock::now();
177 * </code>
178 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500179 * To convert a TimePoint to/from UNIX timestamp:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700180 *
181 * <code>
182 * system_clock::TimePoint time = ...;
183 * uint64_t timestampInMilliseconds = toUnixTimestamp(time).count();
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800184 * system_clock::TimePoint time2 = fromUnixTimestamp(milliseconds(timestampInMilliseconds));
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700185 * </code>
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800186 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800187class system_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800188{
189public:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500190 using duration = boost::chrono::system_clock::duration;
191 using rep = duration::rep;
192 using period = duration::period;
193 using time_point = boost::chrono::time_point<system_clock>;
194 static constexpr bool is_steady = boost::chrono::system_clock::is_steady;
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800195
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700196 typedef time_point TimePoint;
197 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800198
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800199 static time_point
200 now() noexcept;
201
202 static std::time_t
203 to_time_t(const time_point& t) noexcept;
204
205 static time_point
206 from_time_t(std::time_t t) noexcept;
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500207};
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800208
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700209/**
210 * \brief Steady clock
211 *
212 * Steady clock represents a monotonic clock. The time points of this
213 * clock cannot decrease as physical time moves forward. This clock is
214 * not related to wall clock time, and is best suitable for measuring
215 * intervals.
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800216 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800217class steady_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800218{
219public:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500220 using duration = boost::chrono::steady_clock::duration;
221 using rep = duration::rep;
222 using period = duration::period;
223 using time_point = boost::chrono::time_point<steady_clock>;
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800224 static constexpr bool is_steady = true;
225
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700226 typedef time_point TimePoint;
227 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800228
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800229 static time_point
230 now() noexcept;
231
232private:
233 /**
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500234 * \brief Trait function used in detail::SteadyTimer to select proper waiting time
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800235 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500236 * Mock time implementations should return the minimum value to ensure
237 * that Boost.Asio doesn't perform any waiting on mock timers.
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800238 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500239 * @sa http://blog.think-async.com/2007/08/time-travel.html
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800240 */
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500241 static duration
242 to_wait_duration(duration d);
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800243
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500244 friend struct boost::asio::wait_traits<steady_clock>; // see steady-timer.hpp
245};
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800246
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700247/**
248 * \brief Get system_clock::TimePoint representing UNIX time epoch (00:00:00 on Jan 1, 1970)
249 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800250const system_clock::TimePoint&
251getUnixEpoch();
Yingdi Yuf2a82092014-02-03 16:49:15 -0800252
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800253/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700254 * \brief Convert system_clock::TimePoint to UNIX timestamp
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800255 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800256milliseconds
257toUnixTimestamp(const system_clock::TimePoint& point);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800258
259/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700260 * \brief Convert UNIX timestamp to system_clock::TimePoint
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800261 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800262system_clock::TimePoint
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500263fromUnixTimestamp(milliseconds duration);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800264
265/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700266 * \brief Convert to the ISO string representation of the time (YYYYMMDDTHHMMSS,fffffffff)
267 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500268 * If \p timePoint contains doesn't contain fractional seconds,
269 * the output format is YYYYMMDDTHHMMSS
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700270 *
271 * Examples:
272 *
273 * - with fractional nanoseconds: 20020131T100001,123456789
274 * - with fractional microseconds: 20020131T100001,123456
275 * - with fractional milliseconds: 20020131T100001,123
276 * - without fractional seconds: 20020131T100001
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800277 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700278std::string
279toIsoString(const system_clock::TimePoint& timePoint);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800280
281/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700282 * \brief Convert from the ISO string (YYYYMMDDTHHMMSS,fffffffff) representation
283 * to the internal time format
284 *
285 * Examples of accepted ISO strings:
286 *
287 * - with fractional nanoseconds: 20020131T100001,123456789
288 * - with fractional microseconds: 20020131T100001,123456
289 * - with fractional milliseconds: 20020131T100001,123
290 * - without fractional seconds: 20020131T100001
291 *
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800292 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700293system_clock::TimePoint
294fromIsoString(const std::string& isoString);
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700295
296/**
297 * \brief Convert time point to string with specified format
298 *
299 * By default, `%Y-%m-%d %H:%M:%S` is used, producing dates like
300 * `2014-04-10 22:51:00`
301 *
302 * \param timePoint time point of system_clock
303 * \param format desired output format (default: `%Y-%m-%d %H:%M:%S`)
304 * \param locale desired locale (default: "C" locale)
305 *
Davide Pesaventoe6e6fde2016-04-16 14:44:45 +0200306 * \sa http://www.boost.org/doc/libs/1_54_0/doc/html/date_time/date_time_io.html#date_time.format_flags
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500307 * describes possible formatting flags
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700308 **/
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700309std::string
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700310toString(const system_clock::TimePoint& timePoint,
311 const std::string& format = "%Y-%m-%d %H:%M:%S",
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700312 const std::locale& locale = std::locale("C"));
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700313
314/**
315 * \brief Convert from string of specified format into time point
316 *
317 * By default, `%Y-%m-%d %H:%M:%S` is used, accepting dates like
318 * `2014-04-10 22:51:00`
319 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500320 * \param timePointStr string representing time point
321 * \param format input output format (default: `%Y-%m-%d %H:%M:%S`)
322 * \param locale input locale (default: "C" locale)
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700323 *
Davide Pesaventoe6e6fde2016-04-16 14:44:45 +0200324 * \sa http://www.boost.org/doc/libs/1_54_0/doc/html/date_time/date_time_io.html#date_time.format_flags
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500325 * describes possible formatting flags
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700326 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700327system_clock::TimePoint
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500328fromString(const std::string& timePointStr,
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700329 const std::string& format = "%Y-%m-%d %H:%M:%S",
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700330 const std::locale& locale = std::locale("C"));
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800331
332} // namespace time
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -0800333} // namespace ndn
334
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800335namespace boost {
336namespace chrono {
337
338template<class CharT>
339struct clock_string<ndn::time::system_clock, CharT>
340{
341 static std::basic_string<CharT>
342 since();
343};
344
345template<class CharT>
346struct clock_string<ndn::time::steady_clock, CharT>
347{
348 static std::basic_string<CharT>
349 since();
350};
351
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500352extern template struct clock_string<ndn::time::system_clock, char>;
353extern template struct clock_string<ndn::time::steady_clock, char>;
354
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800355} // namespace chrono
356} // namespace boost
357
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500358#endif // NDN_UTIL_TIME_HPP