Skip to content

Commit

Permalink
Format timestamps using ISO 8601 formatting (e.g. "2018-02-28T12:34:5…
Browse files Browse the repository at this point in the history
…6Z")

* Z is the zone designator for the zero UTC offset.
* T is the delimiter used to separate date and time.

This makes it clear for the end-user that the date/time logged is
specified in UTC and not in the local time zone.

Cherry-picked from: a7324bd
  • Loading branch information
practicalswift authored and xanimo committed Apr 1, 2024
1 parent cd43e6a commit d99cc67
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
OpenDebugLog();

if (!fLogTimestamps)
LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", GetDataDir().string());
LogPrintf("Using backup directory %s\n", GetBackupDir().string());
Expand Down
2 changes: 1 addition & 1 deletion src/test/bitcoin-util-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
level = logging.DEBUG
else:
level = logging.ERROR
formatter = '%(asctime)s - %(levelname)s - %(message)s'
formatter = '%(asctime)s.%(msecs)03d000Z %(name)s (%(levelname)s): %(message)s'
# Add the format/level to the logger
logging.basicConfig(format = formatter, level=level)

Expand Down
17 changes: 17 additions & 0 deletions src/test/util_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,27 @@ BOOST_AUTO_TEST_CASE(util_DateTimeStrFormat)
BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 0), "1970-01-01 00:00:00");
BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 0x7FFFFFFF), "2038-01-19 03:14:07");
BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 1317425777), "2011-09-30 23:36:17");
BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", 1317425777), "2011-09-30T23:36:17Z");
BOOST_CHECK_EQUAL(DateTimeStrFormat("%H:%M:%SZ", 1317425777), "23:36:17Z");
BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M", 1317425777), "2011-09-30 23:36");
BOOST_CHECK_EQUAL(DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", 1317425777), "Fri, 30 Sep 2011 23:36:17 +0000");
}

BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
{
BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
}

BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
{
BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
}

BOOST_AUTO_TEST_CASE(util_FormatISO8601Time)
{
BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z");
}

BOOST_AUTO_TEST_CASE(util_ParseParameters)
{
const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"};
Expand Down
14 changes: 10 additions & 4 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,16 @@ static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fSt
return str;

if (*fStartedNewLine) {
int64_t nTimeMicros = GetLogTimeMicros();
strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nTimeMicros/1000000);
if (fLogTimeMicros)
strStamped += strprintf(".%06d", nTimeMicros%1000000);
int64_t nTimeMicros = GetTimeMicros();
strStamped = FormatISO8601DateTime(nTimeMicros/1000000);
if (fLogTimeMicros) {
strStamped.pop_back();
strStamped += strprintf(".%06dZ", nTimeMicros%1000000);
}
int64_t mocktime = GetMockTime();
if (mocktime) {
strStamped += " (mocktime: " + FormatISO8601DateTime(mocktime) + ")";
}
strStamped += ' ' + str;
} else
strStamped = str;
Expand Down
12 changes: 12 additions & 0 deletions src/utiltime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,15 @@ std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
ss << boost::posix_time::from_time_t(nTime);
return ss.str();
}

std::string FormatISO8601DateTime(int64_t nTime) {
return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
}

std::string FormatISO8601Date(int64_t nTime) {
return DateTimeStrFormat("%Y-%m-%d", nTime);
}

std::string FormatISO8601Time(int64_t nTime) {
return DateTimeStrFormat("%H:%M:%SZ", nTime);
}
8 changes: 8 additions & 0 deletions src/utiltime.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ int64_t GetMockTime();
template <typename T>
T GetTime();

/**
* ISO 8601 formatting is preferred. Use the FormatISO8601{DateTime,Date,Time}
* helper functions if possible.
*/
std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime);

std::string FormatISO8601DateTime(int64_t nTime);
std::string FormatISO8601Date(int64_t nTime);
std::string FormatISO8601Time(int64_t nTime);

#endif // BITCOIN_UTILTIME_H
13 changes: 6 additions & 7 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1343,13 +1343,12 @@ void static InvalidChainFound(CBlockIndex* pindexNew)

LogPrintf("%s: invalid block=%s height=%d log2_work=%.8g date=%s\n", __func__,
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,
log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
pindexNew->GetBlockTime()));
log(pindexNew->nChainWork.getdouble())/log(2.0), FormatISO8601DateTime(pindexNew->GetBlockTime()));
CBlockIndex *tip = chainActive.Tip();
assert (tip);
LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__,
tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", tip->GetBlockTime()));
FormatISO8601DateTime(tip->GetBlockTime()));
CheckForkWarningConditions();
}

Expand Down Expand Up @@ -2231,10 +2230,10 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
}
}
}
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utx)", __func__,
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__,
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion,
log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()),
GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
if (!warningMessages.empty())
LogPrintf(" warning='%s'", warningMessages); /* Continued */
Expand Down Expand Up @@ -3760,7 +3759,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams)

LogPrintf("%s: hashBestChain=%s height=%d date=%s progress=%f\n", __func__,
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()),
GuessVerificationProgress(chainparams.TxData(), chainActive.Tip()));

return true;
Expand Down Expand Up @@ -4333,7 +4332,7 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams)

std::string CBlockFileInfo::ToString() const
{
return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst), DateTimeStrFormat("%Y-%m-%d", nTimeLast));
return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast));
}

CBlockFileInfo* GetBlockFileInfo(size_t n)
Expand Down
10 changes: 3 additions & 7 deletions src/wallet/rpcdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ bool EnsureWalletIsAvailable(bool avoidException);
uint32_t getHeightParamFromRequest(const JSONRPCRequest& request, size_t pos);
void attemptRescanFromHeight(uint32_t nHeight);

std::string static EncodeDumpTime(int64_t nTime) {
return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
}

int64_t static DecodeDumpTime(const std::string &str) {
static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
static const std::locale loc(std::locale::classic(),
Expand Down Expand Up @@ -634,9 +630,9 @@ UniValue dumpwallet(const JSONRPCRequest& request)

// produce output
file << strprintf("# Wallet dump created by Dogecoin %s\n", CLIENT_BUILD);
file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()));
file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));
file << strprintf("# mined on %s\n", FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()));
file << "\n";

// add the base58check encoded extended master if the wallet uses HD
Expand All @@ -657,7 +653,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
}
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;
std::string strTime = EncodeDumpTime(it->first);
std::string strTime = FormatISO8601DateTime(it->first);
std::string strAddr = CBitcoinAddress(keyid).ToString();
CKey key;
if (pwalletMain->GetKey(keyid, key)) {
Expand Down

0 comments on commit d99cc67

Please sign in to comment.