blob: 29274a5cf0b88fdf30b5ec33155307fb048d6fd4 [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
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070056/**
57 * \brief System clock
58 *
59 * System clock represents the system-wide real time wall clock.
60 *
61 * It may not be monotonic: on most systems, the system time can be
62 * adjusted at any moment. It is the only clock that has the ability
63 * to be displayed and converted to/from UNIX timestamp.
64 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050065 * To get the current time:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070066 *
67 * <code>
68 * system_clock::TimePoint now = system_clock::now();
69 * </code>
70 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050071 * To convert a TimePoint to/from UNIX timestamp:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070072 *
73 * <code>
74 * system_clock::TimePoint time = ...;
75 * uint64_t timestampInMilliseconds = toUnixTimestamp(time).count();
Alexander Afanasyev85b17b82014-11-10 16:22:05 -080076 * system_clock::TimePoint time2 = fromUnixTimestamp(milliseconds(timestampInMilliseconds));
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070077 * </code>
Alexander Afanasyevf6468892014-01-29 01:04:14 -080078 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -080079class system_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -080080{
81public:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050082 using duration = boost::chrono::system_clock::duration;
83 using rep = duration::rep;
84 using period = duration::period;
85 using time_point = boost::chrono::time_point<system_clock>;
86 static constexpr bool is_steady = boost::chrono::system_clock::is_steady;
Alexander Afanasyev85b17b82014-11-10 16:22:05 -080087
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070088 typedef time_point TimePoint;
89 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -080090
Alexander Afanasyev85b17b82014-11-10 16:22:05 -080091 static time_point
92 now() noexcept;
93
94 static std::time_t
95 to_time_t(const time_point& t) noexcept;
96
97 static time_point
98 from_time_t(std::time_t t) noexcept;
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050099};
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800100
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700101/**
102 * \brief Steady clock
103 *
104 * Steady clock represents a monotonic clock. The time points of this
105 * clock cannot decrease as physical time moves forward. This clock is
106 * not related to wall clock time, and is best suitable for measuring
107 * intervals.
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800108 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800109class steady_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800110{
111public:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500112 using duration = boost::chrono::steady_clock::duration;
113 using rep = duration::rep;
114 using period = duration::period;
115 using time_point = boost::chrono::time_point<steady_clock>;
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800116 static constexpr bool is_steady = true;
117
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700118 typedef time_point TimePoint;
119 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800120
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800121 static time_point
122 now() noexcept;
123
124private:
125 /**
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500126 * \brief Trait function used in detail::SteadyTimer to select proper waiting time
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800127 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500128 * Mock time implementations should return the minimum value to ensure
129 * that Boost.Asio doesn't perform any waiting on mock timers.
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800130 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500131 * @sa http://blog.think-async.com/2007/08/time-travel.html
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800132 */
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500133 static duration
134 to_wait_duration(duration d);
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800135
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500136 friend struct boost::asio::wait_traits<steady_clock>; // see steady-timer.hpp
137};
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800138
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700139/**
140 * \brief Get system_clock::TimePoint representing UNIX time epoch (00:00:00 on Jan 1, 1970)
141 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800142const system_clock::TimePoint&
143getUnixEpoch();
Yingdi Yuf2a82092014-02-03 16:49:15 -0800144
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800145/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700146 * \brief Convert system_clock::TimePoint to UNIX timestamp
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800147 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800148milliseconds
149toUnixTimestamp(const system_clock::TimePoint& point);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800150
151/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700152 * \brief Convert UNIX timestamp to system_clock::TimePoint
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800153 */
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800154system_clock::TimePoint
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500155fromUnixTimestamp(milliseconds duration);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800156
157/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700158 * \brief Convert to the ISO string representation of the time (YYYYMMDDTHHMMSS,fffffffff)
159 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500160 * If \p timePoint contains doesn't contain fractional seconds,
161 * the output format is YYYYMMDDTHHMMSS
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700162 *
163 * Examples:
164 *
165 * - with fractional nanoseconds: 20020131T100001,123456789
166 * - with fractional microseconds: 20020131T100001,123456
167 * - with fractional milliseconds: 20020131T100001,123
168 * - without fractional seconds: 20020131T100001
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800169 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700170std::string
171toIsoString(const system_clock::TimePoint& timePoint);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800172
173/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700174 * \brief Convert from the ISO string (YYYYMMDDTHHMMSS,fffffffff) representation
175 * to the internal time format
176 *
177 * Examples of accepted ISO strings:
178 *
179 * - with fractional nanoseconds: 20020131T100001,123456789
180 * - with fractional microseconds: 20020131T100001,123456
181 * - with fractional milliseconds: 20020131T100001,123
182 * - without fractional seconds: 20020131T100001
183 *
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800184 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700185system_clock::TimePoint
186fromIsoString(const std::string& isoString);
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700187
188/**
189 * \brief Convert time point to string with specified format
190 *
191 * By default, `%Y-%m-%d %H:%M:%S` is used, producing dates like
192 * `2014-04-10 22:51:00`
193 *
194 * \param timePoint time point of system_clock
195 * \param format desired output format (default: `%Y-%m-%d %H:%M:%S`)
196 * \param locale desired locale (default: "C" locale)
197 *
Davide Pesaventoe6e6fde2016-04-16 14:44:45 +0200198 * \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 -0500199 * describes possible formatting flags
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700200 **/
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700201std::string
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700202toString(const system_clock::TimePoint& timePoint,
203 const std::string& format = "%Y-%m-%d %H:%M:%S",
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700204 const std::locale& locale = std::locale("C"));
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700205
206/**
207 * \brief Convert from string of specified format into time point
208 *
209 * By default, `%Y-%m-%d %H:%M:%S` is used, accepting dates like
210 * `2014-04-10 22:51:00`
211 *
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500212 * \param timePointStr string representing time point
213 * \param format input output format (default: `%Y-%m-%d %H:%M:%S`)
214 * \param locale input locale (default: "C" locale)
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700215 *
Davide Pesaventoe6e6fde2016-04-16 14:44:45 +0200216 * \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 -0500217 * describes possible formatting flags
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700218 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700219system_clock::TimePoint
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500220fromString(const std::string& timePointStr,
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700221 const std::string& format = "%Y-%m-%d %H:%M:%S",
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700222 const std::locale& locale = std::locale("C"));
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800223
224} // namespace time
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -0800225} // namespace ndn
226
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800227namespace boost {
228namespace chrono {
229
230template<class CharT>
231struct clock_string<ndn::time::system_clock, CharT>
232{
233 static std::basic_string<CharT>
234 since();
235};
236
237template<class CharT>
238struct clock_string<ndn::time::steady_clock, CharT>
239{
240 static std::basic_string<CharT>
241 since();
242};
243
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500244extern template struct clock_string<ndn::time::system_clock, char>;
245extern template struct clock_string<ndn::time::steady_clock, char>;
246
Alexander Afanasyev85b17b82014-11-10 16:22:05 -0800247} // namespace chrono
248} // namespace boost
249
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500250#endif // NDN_UTIL_TIME_HPP