Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #if defined(HAVE_CONFIG_H)
# 7 : : #include <config/bitcoin-config.h>
# 8 : : #endif
# 9 : :
# 10 : : #include <compat.h>
# 11 : : #include <util/time.h>
# 12 : :
# 13 : : #include <util/check.h>
# 14 : :
# 15 : : #include <atomic>
# 16 : : #include <boost/date_time/posix_time/posix_time.hpp>
# 17 : : #include <ctime>
# 18 : : #include <thread>
# 19 : :
# 20 : : #include <tinyformat.h>
# 21 : :
# 22 : 815 : void UninterruptibleSleep(const std::chrono::microseconds& n) { std::this_thread::sleep_for(n); }
# 23 : :
# 24 : : static std::atomic<int64_t> nMockTime(0); //!< For testing
# 25 : :
# 26 : : int64_t GetTime()
# 27 : 3774140 : {
# 28 : 3774140 : int64_t mocktime = nMockTime.load(std::memory_order_relaxed);
# 29 [ + + ]: 3774140 : if (mocktime) return mocktime;
# 30 : :
# 31 : 3351789 : time_t now = time(nullptr);
# 32 : 3351789 : assert(now > 0);
# 33 : 3351789 : return now;
# 34 : 3351789 : }
# 35 : :
# 36 : : bool ChronoSanityCheck()
# 37 : 666 : {
# 38 : : // std::chrono::system_clock.time_since_epoch and time_t(0) are not guaranteed
# 39 : : // to use the Unix epoch timestamp, prior to C++20, but in practice they almost
# 40 : : // certainly will. Any differing behavior will be assumed to be an error, unless
# 41 : : // certain platforms prove to consistently deviate, at which point we'll cope
# 42 : : // with it by adding offsets.
# 43 : :
# 44 : : // Create a new clock from time_t(0) and make sure that it represents 0
# 45 : : // seconds from the system_clock's time_since_epoch. Then convert that back
# 46 : : // to a time_t and verify that it's the same as before.
# 47 : 666 : const time_t time_t_epoch{};
# 48 : 666 : auto clock = std::chrono::system_clock::from_time_t(time_t_epoch);
# 49 [ - + ]: 666 : if (std::chrono::duration_cast<std::chrono::seconds>(clock.time_since_epoch()).count() != 0) {
# 50 : 0 : return false;
# 51 : 0 : }
# 52 : :
# 53 : 666 : time_t time_val = std::chrono::system_clock::to_time_t(clock);
# 54 [ - + ]: 666 : if (time_val != time_t_epoch) {
# 55 : 0 : return false;
# 56 : 0 : }
# 57 : :
# 58 : : // Check that the above zero time is actually equal to the known unix timestamp.
# 59 : 666 : struct tm epoch;
# 60 : 666 : #ifdef HAVE_GMTIME_R
# 61 [ - + ]: 666 : if (gmtime_r(&time_val, &epoch) == nullptr) {
# 62 : : #else
# 63 : : if (gmtime_s(&epoch, &time_val) != 0) {
# 64 : : #endif
# 65 : 0 : return false;
# 66 : 0 : }
# 67 : :
# 68 [ - + ]: 666 : if ((epoch.tm_sec != 0) ||
# 69 [ - + ]: 666 : (epoch.tm_min != 0) ||
# 70 [ - + ]: 666 : (epoch.tm_hour != 0) ||
# 71 [ - + ]: 666 : (epoch.tm_mday != 1) ||
# 72 [ - + ]: 666 : (epoch.tm_mon != 0) ||
# 73 [ - + ]: 666 : (epoch.tm_year != 70)) {
# 74 : 0 : return false;
# 75 : 0 : }
# 76 : 666 : return true;
# 77 : 666 : }
# 78 : :
# 79 : : template <typename T>
# 80 : : T GetTime()
# 81 : 1015383 : {
# 82 : 1015383 : const std::chrono::seconds mocktime{nMockTime.load(std::memory_order_relaxed)};
# 83 : :
# 84 : 1015383 : return std::chrono::duration_cast<T>(
# 85 [ + + ][ + + ]: 1015383 : mocktime.count() ?
# [ + + ]
# 86 : 54024 : mocktime :
# 87 : 1015383 : std::chrono::microseconds{GetTimeMicros()});
# 88 : 1015383 : }
# 89 : : template std::chrono::seconds GetTime();
# 90 : : template std::chrono::milliseconds GetTime();
# 91 : : template std::chrono::microseconds GetTime();
# 92 : :
# 93 : : template <typename T>
# 94 : : static T GetSystemTime()
# 95 : 7506001 : {
# 96 : 7506001 : const auto now = std::chrono::duration_cast<T>(std::chrono::system_clock::now().time_since_epoch());
# 97 : 7506001 : assert(now.count() > 0);
# 98 : 7506001 : return now;
# 99 : 7506001 : }
# 100 : :
# 101 : : void SetMockTime(int64_t nMockTimeIn)
# 102 : 6526 : {
# 103 : 6526 : Assert(nMockTimeIn >= 0);
# 104 : 6526 : nMockTime.store(nMockTimeIn, std::memory_order_relaxed);
# 105 : 6526 : }
# 106 : :
# 107 : : void SetMockTime(std::chrono::seconds mock_time_in)
# 108 : 851 : {
# 109 : 851 : nMockTime.store(mock_time_in.count(), std::memory_order_relaxed);
# 110 : 851 : }
# 111 : :
# 112 : : std::chrono::seconds GetMockTime()
# 113 : 4054897 : {
# 114 : 4054897 : return std::chrono::seconds(nMockTime.load(std::memory_order_relaxed));
# 115 : 4054897 : }
# 116 : :
# 117 : : int64_t GetTimeMillis()
# 118 : 12830 : {
# 119 : 12830 : return int64_t{GetSystemTime<std::chrono::milliseconds>().count()};
# 120 : 12830 : }
# 121 : :
# 122 : : int64_t GetTimeMicros()
# 123 : 6306062 : {
# 124 : 6306062 : return int64_t{GetSystemTime<std::chrono::microseconds>().count()};
# 125 : 6306062 : }
# 126 : :
# 127 : : int64_t GetSystemTimeInSeconds()
# 128 : 1187137 : {
# 129 : 1187137 : return int64_t{GetSystemTime<std::chrono::seconds>().count()};
# 130 : 1187137 : }
# 131 : :
# 132 : 4354471 : std::string FormatISO8601DateTime(int64_t nTime) {
# 133 : 4354471 : struct tm ts;
# 134 : 4354471 : time_t time_val = nTime;
# 135 : 4354471 : #ifdef HAVE_GMTIME_R
# 136 [ - + ]: 4354471 : if (gmtime_r(&time_val, &ts) == nullptr) {
# 137 : : #else
# 138 : : if (gmtime_s(&ts, &time_val) != 0) {
# 139 : : #endif
# 140 : 0 : return {};
# 141 : 0 : }
# 142 : 4354471 : return strprintf("%04i-%02i-%02iT%02i:%02i:%02iZ", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec);
# 143 : 4354471 : }
# 144 : :
# 145 : 1266 : std::string FormatISO8601Date(int64_t nTime) {
# 146 : 1266 : struct tm ts;
# 147 : 1266 : time_t time_val = nTime;
# 148 : 1266 : #ifdef HAVE_GMTIME_R
# 149 [ - + ]: 1266 : if (gmtime_r(&time_val, &ts) == nullptr) {
# 150 : : #else
# 151 : : if (gmtime_s(&ts, &time_val) != 0) {
# 152 : : #endif
# 153 : 0 : return {};
# 154 : 0 : }
# 155 : 1266 : return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday);
# 156 : 1266 : }
# 157 : :
# 158 : : int64_t ParseISO8601DateTime(const std::string& str)
# 159 : 1725 : {
# 160 : 1725 : static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
# 161 : 1725 : static const std::locale loc(std::locale::classic(),
# 162 : 1725 : new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ"));
# 163 : 1725 : std::istringstream iss(str);
# 164 : 1725 : iss.imbue(loc);
# 165 : 1725 : boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
# 166 : 1725 : iss >> ptime;
# 167 [ + + ][ + + ]: 1725 : if (ptime.is_not_a_date_time() || epoch > ptime)
# 168 : 861 : return 0;
# 169 : 864 : return (ptime - epoch).total_seconds();
# 170 : 864 : }
# 171 : :
# 172 : : struct timeval MillisToTimeval(int64_t nTimeout)
# 173 : 562 : {
# 174 : 562 : struct timeval timeout;
# 175 : 562 : timeout.tv_sec = nTimeout / 1000;
# 176 : 562 : timeout.tv_usec = (nTimeout % 1000) * 1000;
# 177 : 562 : return timeout;
# 178 : 562 : }
# 179 : :
# 180 : : struct timeval MillisToTimeval(std::chrono::milliseconds ms)
# 181 : 562 : {
# 182 : 562 : return MillisToTimeval(count_milliseconds(ms));
# 183 : 562 : }
|