blob: e99a4e91ed4259386213d124b6c2b3451fc4e437 [file] [log] [blame]
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -08001/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -07002 * Copyright (C) 2013-2014 Regents of the University of California.
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -08003 * See COPYING for copyright and distribution information.
4 */
5
6#ifndef NDN_TIME_HPP
7#define NDN_TIME_HPP
8
Alexander Afanasyev19508852014-01-29 01:01:51 -08009#include "../common.hpp"
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070010#include <boost/chrono.hpp>
11#include <boost/date_time/posix_time/posix_time.hpp>
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -080012
13namespace ndn {
Alexander Afanasyevf6468892014-01-29 01:04:14 -080014namespace time {
15
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070016using boost::chrono::duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -080017
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070018typedef duration<boost::int_least32_t, boost::ratio<86400> > days;
19using boost::chrono::hours;
20using boost::chrono::minutes;
21using boost::chrono::seconds;
22
23using boost::chrono::milliseconds;
24using boost::chrono::microseconds;
25using boost::chrono::nanoseconds;
26
27using boost::chrono::duration_cast;
28
29/**
30 * \brief System clock
31 *
32 * System clock represents the system-wide real time wall clock.
33 *
34 * It may not be monotonic: on most systems, the system time can be
35 * adjusted at any moment. It is the only clock that has the ability
36 * to be displayed and converted to/from UNIX timestamp.
37 *
38 * To get current TimePoint:
39 *
40 * <code>
41 * system_clock::TimePoint now = system_clock::now();
42 * </code>
43 *
44 * To convert TimePoint to/from UNIX timestamp:
45 *
46 * <code>
47 * system_clock::TimePoint time = ...;
48 * uint64_t timestampInMilliseconds = toUnixTimestamp(time).count();
49 * system_clock::TimePoint time2 = fromUnixTimestamp(time::milliseconds(timestampInMilliseconds));
50 * </code>
Alexander Afanasyevf6468892014-01-29 01:04:14 -080051 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070052class system_clock : public boost::chrono::system_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -080053{
54public:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070055 typedef time_point TimePoint;
56 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -080057
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070058 // /// \brief Get current TimePoint
59 // TimePoint
60 // now();
61}; // class system_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -080062
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070063/**
64 * \brief Steady clock
65 *
66 * Steady clock represents a monotonic clock. The time points of this
67 * clock cannot decrease as physical time moves forward. This clock is
68 * not related to wall clock time, and is best suitable for measuring
69 * intervals.
70 *
71 * Note that on OS X platform this defaults to system clock and is not
72 * truly monotonic. Refer to https://svn.boost.org/trac/boost/ticket/7719)
Alexander Afanasyevf6468892014-01-29 01:04:14 -080073 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070074class steady_clock : public
75#ifdef __APPLE__
76// steady_clock may go backwards on OS X platforms, so use system_clock
77// instead
78 boost::chrono::system_clock
79#else
80 boost::chrono::steady_clock
81#endif
Alexander Afanasyevf6468892014-01-29 01:04:14 -080082{
83public:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070084 typedef time_point TimePoint;
85 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -080086
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070087 // /// \brief Get current TimePoint
88 // TimePoint
89 // now();
90}; // class steady_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -080091
Alexander Afanasyevf6468892014-01-29 01:04:14 -080092
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070093/**
94 * \brief Get system_clock::TimePoint representing UNIX time epoch (00:00:00 on Jan 1, 1970)
95 */
96inline const system_clock::TimePoint&
97getUnixEpoch()
Yingdi Yuf2a82092014-02-03 16:49:15 -080098{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070099 static system_clock::TimePoint epoch = system_clock::from_time_t(0);
100 return epoch;
Yingdi Yuf2a82092014-02-03 16:49:15 -0800101}
102
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800103/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700104 * \brief Convert system_clock::TimePoint to UNIX timestamp
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800105 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700106inline milliseconds
107toUnixTimestamp(const system_clock::TimePoint& point)
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800108{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700109 return duration_cast<milliseconds>(point - getUnixEpoch());
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800110}
111
112/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700113 * \brief Convert UNIX timestamp to system_clock::TimePoint
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800114 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700115inline system_clock::TimePoint
116fromUnixTimestamp(const milliseconds& duration)
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800117{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700118 return getUnixEpoch() + duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800119}
120
121/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700122 * \brief Convert to the ISO string representation of the time (YYYYMMDDTHHMMSS,fffffffff)
123 *
124 * If timePoint contains doesn't contain fractional seconds the
125 * output format is YYYYMMDDTHHMMSS
126 *
127 * Examples:
128 *
129 * - with fractional nanoseconds: 20020131T100001,123456789
130 * - with fractional microseconds: 20020131T100001,123456
131 * - with fractional milliseconds: 20020131T100001,123
132 * - without fractional seconds: 20020131T100001
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800133 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700134inline std::string
135toIsoString(const system_clock::TimePoint& timePoint)
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800136{
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700137 namespace bpt = boost::posix_time;
138 bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700139
140 uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
141 if (micro > 0)
142 {
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700143 ptime += bpt::microseconds(micro);
144 return bpt::to_iso_string(ptime);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700145 }
146 else
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700147 return bpt::to_iso_string(ptime);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800148}
149
150/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700151 * \brief Convert from the ISO string (YYYYMMDDTHHMMSS,fffffffff) representation
152 * to the internal time format
153 *
154 * Examples of accepted ISO strings:
155 *
156 * - with fractional nanoseconds: 20020131T100001,123456789
157 * - with fractional microseconds: 20020131T100001,123456
158 * - with fractional milliseconds: 20020131T100001,123
159 * - without fractional seconds: 20020131T100001
160 *
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800161 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700162inline system_clock::TimePoint
163fromIsoString(const std::string& isoString)
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800164{
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700165 namespace bpt = boost::posix_time;
166 static bpt::ptime posixTimeEpoch = bpt::from_time_t(0);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800167
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700168 bpt::ptime ptime = bpt::from_iso_string(isoString);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700169
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700170 system_clock::TimePoint point =
171 system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
172 point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
173 return point;
174}
175
176/**
177 * \brief Convert time point to string with specified format
178 *
179 * By default, `%Y-%m-%d %H:%M:%S` is used, producing dates like
180 * `2014-04-10 22:51:00`
181 *
182 * \param timePoint time point of system_clock
183 * \param format desired output format (default: `%Y-%m-%d %H:%M:%S`)
184 * \param locale desired locale (default: "C" locale)
185 *
186 * \sa http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/date_time_io.html#date_time.format_flags
187 * described possible formatting flags
188 **/
189inline std::string
190toString(const system_clock::TimePoint& timePoint,
191 const std::string& format = "%Y-%m-%d %H:%M:%S",
192 const std::locale& locale = std::locale("C"))
193{
194 namespace bpt = boost::posix_time;
195 bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
196
197 uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
198 ptime += bpt::microseconds(micro);
199
200 bpt::time_facet* facet = new bpt::time_facet(format.c_str());
201 std::ostringstream formattedTimePoint;
202 formattedTimePoint.imbue(std::locale(locale, facet));
203 formattedTimePoint << ptime;
204
205 return formattedTimePoint.str();
206}
207
208/**
209 * \brief Convert from string of specified format into time point
210 *
211 * By default, `%Y-%m-%d %H:%M:%S` is used, accepting dates like
212 * `2014-04-10 22:51:00`
213 *
214 * \param formattedTimePoint string representing time point
215 * \param format input output format (default: `%Y-%m-%d %H:%M:%S`)
216 * \param locale input locale (default: "C" locale)
217 *
218 * \sa http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/date_time_io.html#date_time.format_flags
219 * described possible formatting flags
220 */
221inline system_clock::TimePoint
222fromString(const std::string& formattedTimePoint,
223 const std::string& format = "%Y-%m-%d %H:%M:%S",
224 const std::locale& locale = std::locale("C"))
225{
226 namespace bpt = boost::posix_time;
227 static bpt::ptime posixTimeEpoch = bpt::from_time_t(0);
228
229 bpt::time_input_facet* facet = new bpt::time_input_facet(format);
230 std::istringstream is(formattedTimePoint);
231
232 is.imbue(std::locale(locale, facet));
233 bpt::ptime ptime;
234 is >> ptime;
235
236 system_clock::TimePoint point =
237 system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700238 point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
239 return point;
240}
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800241
242} // namespace time
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -0800243} // namespace ndn
244
245#endif // NDN_TIME_HPP