blob: 3bc4e4f9287e1cbac7dddc79da5829190dba18f9 [file] [log] [blame]
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -08002/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -080011 */
12
13#ifndef NDN_TIME_HPP
14#define NDN_TIME_HPP
15
Alexander Afanasyev19508852014-01-29 01:01:51 -080016#include "../common.hpp"
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070017#include <boost/chrono.hpp>
18#include <boost/date_time/posix_time/posix_time.hpp>
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -080019
20namespace ndn {
Alexander Afanasyevf6468892014-01-29 01:04:14 -080021namespace time {
22
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070023using boost::chrono::duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -080024
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070025typedef duration<boost::int_least32_t, boost::ratio<86400> > days;
26using boost::chrono::hours;
27using boost::chrono::minutes;
28using boost::chrono::seconds;
29
30using boost::chrono::milliseconds;
31using boost::chrono::microseconds;
32using boost::chrono::nanoseconds;
33
34using boost::chrono::duration_cast;
35
36/**
37 * \brief System clock
38 *
39 * System clock represents the system-wide real time wall clock.
40 *
41 * It may not be monotonic: on most systems, the system time can be
42 * adjusted at any moment. It is the only clock that has the ability
43 * to be displayed and converted to/from UNIX timestamp.
44 *
45 * To get current TimePoint:
46 *
47 * <code>
48 * system_clock::TimePoint now = system_clock::now();
49 * </code>
50 *
51 * To convert TimePoint to/from UNIX timestamp:
52 *
53 * <code>
54 * system_clock::TimePoint time = ...;
55 * uint64_t timestampInMilliseconds = toUnixTimestamp(time).count();
56 * system_clock::TimePoint time2 = fromUnixTimestamp(time::milliseconds(timestampInMilliseconds));
57 * </code>
Alexander Afanasyevf6468892014-01-29 01:04:14 -080058 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070059class system_clock : public boost::chrono::system_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -080060{
61public:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070062 typedef time_point TimePoint;
63 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -080064
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070065 // /// \brief Get current TimePoint
66 // TimePoint
67 // now();
68}; // class system_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -080069
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070070/**
71 * \brief Steady clock
72 *
73 * Steady clock represents a monotonic clock. The time points of this
74 * clock cannot decrease as physical time moves forward. This clock is
75 * not related to wall clock time, and is best suitable for measuring
76 * intervals.
77 *
78 * Note that on OS X platform this defaults to system clock and is not
79 * truly monotonic. Refer to https://svn.boost.org/trac/boost/ticket/7719)
Alexander Afanasyevf6468892014-01-29 01:04:14 -080080 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070081class steady_clock : public
82#ifdef __APPLE__
83// steady_clock may go backwards on OS X platforms, so use system_clock
84// instead
85 boost::chrono::system_clock
86#else
87 boost::chrono::steady_clock
88#endif
Alexander Afanasyevf6468892014-01-29 01:04:14 -080089{
90public:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070091 typedef time_point TimePoint;
92 typedef duration Duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -080093
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070094 // /// \brief Get current TimePoint
95 // TimePoint
96 // now();
97}; // class steady_clock
Alexander Afanasyevf6468892014-01-29 01:04:14 -080098
Alexander Afanasyevf6468892014-01-29 01:04:14 -080099
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700100/**
101 * \brief Get system_clock::TimePoint representing UNIX time epoch (00:00:00 on Jan 1, 1970)
102 */
103inline const system_clock::TimePoint&
104getUnixEpoch()
Yingdi Yuf2a82092014-02-03 16:49:15 -0800105{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700106 static system_clock::TimePoint epoch = system_clock::from_time_t(0);
107 return epoch;
Yingdi Yuf2a82092014-02-03 16:49:15 -0800108}
109
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800110/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700111 * \brief Convert system_clock::TimePoint to UNIX timestamp
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800112 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700113inline milliseconds
114toUnixTimestamp(const system_clock::TimePoint& point)
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800115{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700116 return duration_cast<milliseconds>(point - getUnixEpoch());
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800117}
118
119/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700120 * \brief Convert UNIX timestamp to system_clock::TimePoint
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800121 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700122inline system_clock::TimePoint
123fromUnixTimestamp(const milliseconds& duration)
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800124{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700125 return getUnixEpoch() + duration;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800126}
127
128/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700129 * \brief Convert to the ISO string representation of the time (YYYYMMDDTHHMMSS,fffffffff)
130 *
131 * If timePoint contains doesn't contain fractional seconds the
132 * output format is YYYYMMDDTHHMMSS
133 *
134 * Examples:
135 *
136 * - with fractional nanoseconds: 20020131T100001,123456789
137 * - with fractional microseconds: 20020131T100001,123456
138 * - with fractional milliseconds: 20020131T100001,123
139 * - without fractional seconds: 20020131T100001
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800140 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700141inline std::string
142toIsoString(const system_clock::TimePoint& timePoint)
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800143{
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700144 namespace bpt = boost::posix_time;
145 bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700146
147 uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
148 if (micro > 0)
149 {
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700150 ptime += bpt::microseconds(micro);
151 return bpt::to_iso_string(ptime);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700152 }
153 else
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700154 return bpt::to_iso_string(ptime);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800155}
156
157/**
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700158 * \brief Convert from the ISO string (YYYYMMDDTHHMMSS,fffffffff) representation
159 * to the internal time format
160 *
161 * Examples of accepted ISO strings:
162 *
163 * - with fractional nanoseconds: 20020131T100001,123456789
164 * - with fractional microseconds: 20020131T100001,123456
165 * - with fractional milliseconds: 20020131T100001,123
166 * - without fractional seconds: 20020131T100001
167 *
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800168 */
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700169inline system_clock::TimePoint
170fromIsoString(const std::string& isoString)
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800171{
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700172 namespace bpt = boost::posix_time;
173 static bpt::ptime posixTimeEpoch = bpt::from_time_t(0);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800174
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700175 bpt::ptime ptime = bpt::from_iso_string(isoString);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700176
Alexander Afanasyev53af7a12014-04-10 23:35:28 -0700177 system_clock::TimePoint point =
178 system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
179 point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
180 return point;
181}
182
183/**
184 * \brief Convert time point to string with specified format
185 *
186 * By default, `%Y-%m-%d %H:%M:%S` is used, producing dates like
187 * `2014-04-10 22:51:00`
188 *
189 * \param timePoint time point of system_clock
190 * \param format desired output format (default: `%Y-%m-%d %H:%M:%S`)
191 * \param locale desired locale (default: "C" locale)
192 *
193 * \sa http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/date_time_io.html#date_time.format_flags
194 * described possible formatting flags
195 **/
196inline std::string
197toString(const system_clock::TimePoint& timePoint,
198 const std::string& format = "%Y-%m-%d %H:%M:%S",
199 const std::locale& locale = std::locale("C"))
200{
201 namespace bpt = boost::posix_time;
202 bpt::ptime ptime = bpt::from_time_t(system_clock::to_time_t(timePoint));
203
204 uint64_t micro = duration_cast<microseconds>(timePoint - getUnixEpoch()).count() % 1000000;
205 ptime += bpt::microseconds(micro);
206
207 bpt::time_facet* facet = new bpt::time_facet(format.c_str());
208 std::ostringstream formattedTimePoint;
209 formattedTimePoint.imbue(std::locale(locale, facet));
210 formattedTimePoint << ptime;
211
212 return formattedTimePoint.str();
213}
214
215/**
216 * \brief Convert from string of specified format into time point
217 *
218 * By default, `%Y-%m-%d %H:%M:%S` is used, accepting dates like
219 * `2014-04-10 22:51:00`
220 *
221 * \param formattedTimePoint string representing time point
222 * \param format input output format (default: `%Y-%m-%d %H:%M:%S`)
223 * \param locale input locale (default: "C" locale)
224 *
225 * \sa http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/date_time_io.html#date_time.format_flags
226 * described possible formatting flags
227 */
228inline system_clock::TimePoint
229fromString(const std::string& formattedTimePoint,
230 const std::string& format = "%Y-%m-%d %H:%M:%S",
231 const std::locale& locale = std::locale("C"))
232{
233 namespace bpt = boost::posix_time;
234 static bpt::ptime posixTimeEpoch = bpt::from_time_t(0);
235
236 bpt::time_input_facet* facet = new bpt::time_input_facet(format);
237 std::istringstream is(formattedTimePoint);
238
239 is.imbue(std::locale(locale, facet));
240 bpt::ptime ptime;
241 is >> ptime;
242
243 system_clock::TimePoint point =
244 system_clock::from_time_t((ptime - posixTimeEpoch).total_seconds());
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700245 point += microseconds((ptime - posixTimeEpoch).total_microseconds() % 1000000);
246 return point;
247}
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800248
249} // namespace time
Alexander Afanasyeve2e3ca52014-01-03 13:59:07 -0800250} // namespace ndn
251
252#endif // NDN_TIME_HPP