time.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2021 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * 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.
20  */
21 
22 #include "ndn-cxx/util/time.hpp"
24 
25 #include <boost/date_time/posix_time/posix_time.hpp>
26 #include <sstream>
27 
28 namespace ndn {
29 namespace time {
30 
31 static shared_ptr<CustomSystemClock> g_systemClock;
32 static shared_ptr<CustomSteadyClock> g_steadyClock;
33 
34 // this function is declared in time-custom-clock.hpp
35 void
36 setCustomClocks(shared_ptr<CustomSteadyClock> steadyClock,
37  shared_ptr<CustomSystemClock> systemClock)
38 {
39  g_systemClock = std::move(systemClock);
40  g_steadyClock = std::move(steadyClock);
41 }
42 
44 
47 {
48  if (g_systemClock == nullptr) {
49  // optimized default version
50  return time_point(boost::chrono::system_clock::now().time_since_epoch());
51  }
52  else {
53  return g_systemClock->getNow();
54  }
55 }
56 
57 std::time_t
59 {
60  return duration_cast<seconds>(t.time_since_epoch()).count();
61 }
62 
64 system_clock::from_time_t(std::time_t t) noexcept
65 {
66  return time_point(seconds(t));
67 }
68 
70 
71 #ifdef __APPLE__
72 // Note that on macOS platform boost::steady_clock is not truly monotonic, so we use
73 // system_clock instead. Refer to https://svn.boost.org/trac/boost/ticket/7719)
74 typedef boost::chrono::system_clock base_steady_clock;
75 #else
76 typedef boost::chrono::steady_clock base_steady_clock;
77 #endif
78 
81 {
82  if (g_steadyClock == nullptr) {
83  // optimized default version
84  return time_point(base_steady_clock::now().time_since_epoch());
85  }
86  else {
87  return g_steadyClock->getNow();
88  }
89 }
90 
92 steady_clock::to_wait_duration(steady_clock::duration d)
93 {
94  if (g_steadyClock == nullptr) {
95  // optimized default version
96  return d;
97  }
98  else {
99  return g_steadyClock->toWaitDuration(d);
100  }
101 }
102 
104 
107 {
108  static constexpr system_clock::time_point epoch(seconds::zero());
109  return epoch;
110 }
111 
114 {
115  return duration_cast<milliseconds>(point - getUnixEpoch());
116 }
117 
120 {
121  return getUnixEpoch() + duration;
122 }
123 
124 static boost::posix_time::ptime
125 convertToPosixTime(const system_clock::time_point& timePoint)
126 {
127  namespace bpt = boost::posix_time;
128  static bpt::ptime epoch(boost::gregorian::date(1970, 1, 1));
129 
130  using BptResolution =
131 #if defined(BOOST_DATE_TIME_HAS_NANOSECONDS)
132  nanoseconds;
133 #else
134  microseconds;
135 #endif
136  constexpr auto unitsPerHour = duration_cast<BptResolution>(1_h).count();
137 
138  auto sinceEpoch = duration_cast<BptResolution>(timePoint - getUnixEpoch()).count();
139  return epoch + bpt::time_duration(sinceEpoch / unitsPerHour, 0, 0, sinceEpoch % unitsPerHour);
140 }
141 
142 std::string
144 {
145  return boost::posix_time::to_iso_string(convertToPosixTime(timePoint));
146 }
147 
148 std::string
150 {
151  return boost::posix_time::to_iso_extended_string(convertToPosixTime(timePoint));
152 }
153 
155 convertToTimePoint(const boost::posix_time::ptime& ptime)
156 {
157  namespace bpt = boost::posix_time;
158  static bpt::ptime epoch(boost::gregorian::date(1970, 1, 1));
159 
160  // .total_seconds() has an issue with large dates until Boost 1.66, see #4478.
161  // time_t overflows for large dates on 32-bit platforms (Y2038 problem).
162  auto sinceEpoch = ptime - epoch;
163  auto point = system_clock::time_point(seconds(sinceEpoch.ticks() / bpt::time_duration::ticks_per_second()));
164  return point + microseconds(sinceEpoch.total_microseconds() % 1000000);
165 }
166 
168 fromIsoString(const std::string& isoString)
169 {
170  return convertToTimePoint(boost::posix_time::from_iso_string(isoString));
171 }
172 
174 fromIsoExtendedString(const std::string& isoString)
175 {
176  return convertToTimePoint(boost::posix_time::from_iso_extended_string(isoString));
177 }
178 
179 std::string
181  const std::string& format/* = "%Y-%m-%d %H:%M:%S"*/,
182  const std::locale& locale/* = std::locale("C")*/)
183 {
184  namespace bpt = boost::posix_time;
185 
186  std::ostringstream os;
187  auto* facet = new bpt::time_facet(format.data());
188  os.imbue(std::locale(locale, facet));
189  os << convertToPosixTime(timePoint);
190 
191  return os.str();
192 }
193 
195 fromString(const std::string& timePointStr,
196  const std::string& format/* = "%Y-%m-%d %H:%M:%S"*/,
197  const std::locale& locale/* = std::locale("C")*/)
198 {
199  namespace bpt = boost::posix_time;
200 
201  std::istringstream is(timePointStr);
202  auto* facet = new bpt::time_input_facet(format);
203  is.imbue(std::locale(locale, facet));
204  bpt::ptime ptime;
205  is >> ptime;
206 
207  return convertToTimePoint(ptime);
208 }
209 
210 } // namespace time
211 } // namespace ndn
212 
213 namespace boost {
214 namespace chrono {
215 
216 template<class CharT>
217 std::basic_string<CharT>
219 {
220  if (ndn::time::g_systemClock == nullptr) {
221  // optimized default version
222  return clock_string<system_clock, CharT>::since();
223  }
224  else {
225  return ndn::time::g_systemClock->getSince();
226  }
227 }
228 
229 template<class CharT>
230 std::basic_string<CharT>
232 {
233  if (ndn::time::g_steadyClock == nullptr) {
234  // optimized default version
235  return clock_string<ndn::time::base_steady_clock, CharT>::since();
236  }
237  else {
238  return ndn::time::g_steadyClock->getSince();
239  }
240 }
241 
242 template struct clock_string<ndn::time::system_clock, char>;
243 template struct clock_string<ndn::time::steady_clock, char>;
244 
245 } // namespace chrono
246 } // namespace boost
static time_point now() noexcept
Definition: time.cpp:80
boost::chrono::steady_clock::duration duration
Definition: time.hpp:227
boost::chrono::time_point< steady_clock > time_point
Definition: time.hpp:230
static time_point now() noexcept
Definition: time.cpp:46
static std::time_t to_time_t(const time_point &t) noexcept
Definition: time.cpp:58
boost::chrono::time_point< system_clock > time_point
Definition: time.hpp:200
static time_point from_time_t(std::time_t t) noexcept
Definition: time.cpp:64
std::string toIsoExtendedString(const system_clock::time_point &timePoint)
Convert to the ISO 8601 string representation, extended format (YYYY-MM-DDTHH:MM:SS,...
Definition: time.cpp:149
milliseconds toUnixTimestamp(const system_clock::time_point &point)
Convert system_clock::time_point to UNIX timestamp.
Definition: time.cpp:113
std::string toString(const system_clock::time_point &timePoint, const std::string &format, const std::locale &locale)
Convert time point to string with specified format.
Definition: time.cpp:180
std::string toIsoString(const system_clock::time_point &timePoint)
Convert to the ISO 8601 string representation, basic format (YYYYMMDDTHHMMSS,fffffffff).
Definition: time.cpp:143
const system_clock::time_point & getUnixEpoch()
Return a system_clock::time_point representing the UNIX time epoch, i.e., 00:00:00 UTC on 1 January 1...
Definition: time.cpp:106
boost::chrono::duration< Rep, Period > duration
Definition: time.hpp:34
boost::chrono::milliseconds milliseconds
Definition: time.hpp:48
void setCustomClocks(shared_ptr< CustomSteadyClock > steadyClock=nullptr, shared_ptr< CustomSystemClock > systemClock=nullptr)
Set custom system and steady clocks.
Definition: time.cpp:36
boost::chrono::nanoseconds nanoseconds
Definition: time.hpp:50
boost::chrono::microseconds microseconds
Definition: time.hpp:49
system_clock::time_point fromIsoString(const std::string &isoString)
Convert from the ISO 8601 basic string format (YYYYMMDDTHHMMSS,fffffffff) to the internal time format...
Definition: time.cpp:168
system_clock::time_point fromString(const std::string &timePointStr, const std::string &format, const std::locale &locale)
Convert from string of specified format into time point.
Definition: time.cpp:195
system_clock::time_point fromIsoExtendedString(const std::string &isoString)
Convert from the ISO 8601 extended string format (YYYY-MM-DDTHH:MM:SS,fffffffff) to the internal time...
Definition: time.cpp:174
system_clock::time_point fromUnixTimestamp(milliseconds duration)
Convert UNIX timestamp to system_clock::time_point.
Definition: time.cpp:119
boost::chrono::seconds seconds
Definition: time.hpp:47
boost::chrono::steady_clock base_steady_clock
Definition: time.cpp:76
Definition: data.cpp:25