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-2024 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::time {
29 
30 static std::shared_ptr<CustomSystemClock> g_systemClock;
31 static std::shared_ptr<CustomSteadyClock> g_steadyClock;
32 
33 // this function is declared in time-custom-clock.hpp
34 void
35 setCustomClocks(std::shared_ptr<CustomSteadyClock> steadyClock,
36  std::shared_ptr<CustomSystemClock> systemClock)
37 {
38  g_systemClock = std::move(systemClock);
39  g_steadyClock = std::move(steadyClock);
40 }
41 
43 
46 {
47  if (g_systemClock == nullptr) {
48  // optimized default version
49  return time_point(boost::chrono::system_clock::now().time_since_epoch());
50  }
51  else {
52  return g_systemClock->getNow();
53  }
54 }
55 
56 std::time_t
58 {
59  return duration_cast<seconds>(t.time_since_epoch()).count();
60 }
61 
63 system_clock::from_time_t(std::time_t t) noexcept
64 {
65  return time_point(seconds(t));
66 }
67 
69 
70 #ifdef __APPLE__
71 // Note that on macOS platform boost::steady_clock is not truly monotonic, so we use
72 // system_clock instead. Refer to https://svn.boost.org/trac/boost/ticket/7719)
73 using base_steady_clock = boost::chrono::system_clock;
74 #else
75 using base_steady_clock = boost::chrono::steady_clock;
76 #endif
77 
80 {
81  if (g_steadyClock == nullptr) {
82  // optimized default version
83  return time_point(base_steady_clock::now().time_since_epoch());
84  }
85  else {
86  return g_steadyClock->getNow();
87  }
88 }
89 
91 steady_clock::to_wait_duration(steady_clock::duration d)
92 {
93  if (g_steadyClock == nullptr) {
94  // optimized default version
95  return d;
96  }
97  else {
98  return g_steadyClock->toWaitDuration(d);
99  }
100 }
101 
103 
106 {
107  static constexpr system_clock::time_point epoch;
108  return epoch;
109 }
110 
111 static boost::posix_time::ptime
112 convertToPosixTime(const system_clock::time_point& timePoint)
113 {
114  namespace bpt = boost::posix_time;
115  static bpt::ptime epoch(boost::gregorian::date(1970, 1, 1));
116 
117  using BptResolution =
118 #if defined(BOOST_DATE_TIME_HAS_NANOSECONDS)
119  nanoseconds;
120 #else
121  microseconds;
122 #endif
123  constexpr auto unitsPerHour = duration_cast<BptResolution>(1_h).count();
124 
125  auto sinceEpoch = duration_cast<BptResolution>(timePoint - getUnixEpoch()).count();
126  return epoch + bpt::time_duration(sinceEpoch / unitsPerHour, 0, 0, sinceEpoch % unitsPerHour);
127 }
128 
129 std::string
131 {
132  return boost::posix_time::to_iso_string(convertToPosixTime(timePoint));
133 }
134 
135 std::string
137 {
138  return boost::posix_time::to_iso_extended_string(convertToPosixTime(timePoint));
139 }
140 
142 convertToTimePoint(const boost::posix_time::ptime& ptime)
143 {
144  namespace bpt = boost::posix_time;
145  static bpt::ptime epoch(boost::gregorian::date(1970, 1, 1));
146 
147  // .total_seconds() has an issue with large dates until Boost 1.66, see #4478.
148  // time_t overflows for large dates on 32-bit platforms (Y2038 problem).
149  auto sinceEpoch = ptime - epoch;
150  auto point = system_clock::time_point(seconds(sinceEpoch.ticks() / bpt::time_duration::ticks_per_second()));
151  return point + microseconds(sinceEpoch.total_microseconds() % 1000000);
152 }
153 
155 fromIsoString(const std::string& isoString)
156 {
157  return convertToTimePoint(boost::posix_time::from_iso_string(isoString));
158 }
159 
161 fromIsoExtendedString(const std::string& isoString)
162 {
163  return convertToTimePoint(boost::posix_time::from_iso_extended_string(isoString));
164 }
165 
166 std::string
168  const std::string& format/* = "%Y-%m-%d %H:%M:%S"*/,
169  const std::locale& locale/* = std::locale("C")*/)
170 {
171  namespace bpt = boost::posix_time;
172 
173  std::ostringstream os;
174  auto* facet = new bpt::time_facet(format.data());
175  os.imbue(std::locale(locale, facet));
176  os << convertToPosixTime(timePoint);
177 
178  return os.str();
179 }
180 
182 fromString(const std::string& timePointStr,
183  const std::string& format/* = "%Y-%m-%d %H:%M:%S"*/,
184  const std::locale& locale/* = std::locale("C")*/)
185 {
186  namespace bpt = boost::posix_time;
187 
188  std::istringstream is(timePointStr);
189  auto* facet = new bpt::time_input_facet(format);
190  is.imbue(std::locale(locale, facet));
191  bpt::ptime ptime;
192  is >> ptime;
193 
194  return convertToTimePoint(ptime);
195 }
196 
197 } // namespace ndn::time
198 
199 namespace boost::chrono {
200 
201 template<class CharT>
202 std::basic_string<CharT>
203 clock_string<ndn::time::system_clock, CharT>::since()
204 {
205  if (ndn::time::g_systemClock == nullptr) {
206  // optimized default version
207  return clock_string<system_clock, CharT>::since();
208  }
209  else {
210  return ndn::time::g_systemClock->getSince();
211  }
212 }
213 
214 template<class CharT>
215 std::basic_string<CharT>
216 clock_string<ndn::time::steady_clock, CharT>::since()
217 {
218  if (ndn::time::g_steadyClock == nullptr) {
219  // optimized default version
220  return clock_string<ndn::time::base_steady_clock, CharT>::since();
221  }
222  else {
223  return ndn::time::g_steadyClock->getSince();
224  }
225 }
226 
227 template struct clock_string<ndn::time::system_clock, char>;
228 template struct clock_string<ndn::time::steady_clock, char>;
229 
230 } // namespace boost::chrono
static time_point now() noexcept
Definition: time.cpp:79
::boost::chrono::steady_clock::duration duration
Definition: time.hpp:229
::boost::chrono::time_point< steady_clock > time_point
Definition: time.hpp:232
static time_point now() noexcept
Definition: time.cpp:45
static std::time_t to_time_t(const time_point &t) noexcept
Definition: time.cpp:57
::boost::chrono::time_point< system_clock > time_point
Definition: time.hpp:205
static time_point from_time_t(std::time_t t) noexcept
Definition: time.cpp:63
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:136
boost::chrono::steady_clock base_steady_clock
Definition: time.cpp:75
void setCustomClocks(std::shared_ptr< CustomSteadyClock > steadyClock=nullptr, std::shared_ptr< CustomSystemClock > systemClock=nullptr)
Set custom system and steady clocks.
Definition: time.cpp:35
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:167
::boost::chrono::seconds seconds
Definition: time.hpp:51
std::string toIsoString(const system_clock::time_point &timePoint)
Convert to the ISO 8601 string representation, basic format (YYYYMMDDTHHMMSS,fffffffff).
Definition: time.cpp:130
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:105
::boost::chrono::microseconds microseconds
Definition: time.hpp:53
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:155
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:182
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:161
::boost::chrono::nanoseconds nanoseconds
Definition: time.hpp:54