feat(util): app-wide 24h/12h clock format
Add util::formatClockDateTime/formatClockTime driven by a process-wide flag (setClock12h, synced from the time_format setting each frame). Switch the primary user-facing timestamp displays to it — the transaction list, wallet-state tx + banned-peer times, the explorer block time, and the block-info dialog — so one preference drives every clock. Log files, export filenames/content, console line prefixes, the market chart axis, and the worker-thread "last updated" string intentionally stay fixed 24h. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
// Released under the GPLv3
|
// Released under the GPLv3
|
||||||
|
|
||||||
#include "wallet_state.h"
|
#include "wallet_state.h"
|
||||||
|
#include "../util/text_format.h" // util::formatClockDateTime (app-wide 24h/12h clock)
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -44,13 +45,7 @@ int bestSpendableAddressIndex(const std::vector<AddressInfo>& addresses)
|
|||||||
std::string TransactionInfo::getTimeString() const
|
std::string TransactionInfo::getTimeString() const
|
||||||
{
|
{
|
||||||
if (timestamp == 0) return "Unknown";
|
if (timestamp == 0) return "Unknown";
|
||||||
|
return util::formatClockDateTime(timestamp);
|
||||||
std::time_t t = static_cast<std::time_t>(timestamp);
|
|
||||||
std::tm* tm = std::localtime(&t);
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << std::put_time(tm, "%Y-%m-%d %H:%M");
|
|
||||||
return ss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TransactionInfo::getTypeDisplay() const
|
std::string TransactionInfo::getTypeDisplay() const
|
||||||
@@ -77,13 +72,7 @@ std::string PeerInfo::getConnectionTime() const
|
|||||||
std::string BannedPeer::getBannedUntilString() const
|
std::string BannedPeer::getBannedUntilString() const
|
||||||
{
|
{
|
||||||
if (banned_until == 0) return "Never";
|
if (banned_until == 0) return "Never";
|
||||||
|
return util::formatClockDateTime(banned_until);
|
||||||
std::time_t t = static_cast<std::time_t>(banned_until);
|
|
||||||
std::tm* tm = std::localtime(&t);
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << std::put_time(tm, "%Y-%m-%d %H:%M");
|
|
||||||
return ss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dragonx
|
} // namespace dragonx
|
||||||
|
|||||||
@@ -203,10 +203,7 @@ void BlockInfoDialog::render(App* app)
|
|||||||
ImGui::Text("%s", TR("block_timestamp"));
|
ImGui::Text("%s", TR("block_timestamp"));
|
||||||
ImGui::SameLine(lbl.position);
|
ImGui::SameLine(lbl.position);
|
||||||
if (s_block_time > 0) {
|
if (s_block_time > 0) {
|
||||||
std::time_t t = static_cast<std::time_t>(s_block_time);
|
ImGui::Text("%s", dragonx::util::formatClockDateTime(s_block_time, /*withSeconds=*/true).c_str());
|
||||||
char time_buf[64];
|
|
||||||
std::strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", std::localtime(&t));
|
|
||||||
ImGui::Text("%s", time_buf);
|
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextDisabled("%s", TR("unknown"));
|
ImGui::TextDisabled("%s", TR("unknown"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1127,10 +1127,8 @@ static void renderBlockDetailModal(App* app) {
|
|||||||
// Row 1: Timestamp | Confirmations
|
// Row 1: Timestamp | Confirmations
|
||||||
drawLabelValue(dl, gx, gy, labelW, TR("block_timestamp"), "", capFont, sub1);
|
drawLabelValue(dl, gx, gy, labelW, TR("block_timestamp"), "", capFont, sub1);
|
||||||
if (s_detail_time > 0) {
|
if (s_detail_time > 0) {
|
||||||
std::time_t t = static_cast<std::time_t>(s_detail_time);
|
const std::string tstr = dragonx::util::formatClockDateTime(s_detail_time, /*withSeconds=*/true);
|
||||||
char time_buf[64];
|
dl->AddText(sub1, sub1->LegacySize, ImVec2(gx + labelW, gy), OnSurface(), tstr.c_str());
|
||||||
std::strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", std::localtime(&t));
|
|
||||||
dl->AddText(sub1, sub1->LegacySize, ImVec2(gx + labelW, gy), OnSurface(), time_buf);
|
|
||||||
}
|
}
|
||||||
dl->AddText(capFont, capFont->LegacySize, ImVec2(gx + halfW, gy), OnSurfaceMedium(), TR("confirmations"));
|
dl->AddText(capFont, capFont->LegacySize, ImVec2(gx + halfW, gy), OnSurfaceMedium(), TR("confirmations"));
|
||||||
snprintf(buf, sizeof(buf), "%d", s_detail_confirmations);
|
snprintf(buf, sizeof(buf), "%d", s_detail_confirmations);
|
||||||
|
|||||||
@@ -64,10 +64,7 @@ struct DisplayTx {
|
|||||||
|
|
||||||
std::string DisplayTx::getTimeString() const {
|
std::string DisplayTx::getTimeString() const {
|
||||||
if (timestamp <= 0) return TR("pending");
|
if (timestamp <= 0) return TR("pending");
|
||||||
std::time_t t = static_cast<std::time_t>(timestamp);
|
return dragonx::util::formatClockDateTime(timestamp); // honors the app-wide 24h/12h clock
|
||||||
char buf[64];
|
|
||||||
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M", std::localtime(&t));
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relative time string (localized long form, e.g. "5 minutes ago")
|
// Relative time string (localized long form, e.g. "5 minutes ago")
|
||||||
|
|||||||
@@ -19,8 +19,38 @@ std::int64_t secondsAgo(std::int64_t timestamp)
|
|||||||
std::int64_t diff = now - timestamp;
|
std::int64_t diff = now - timestamp;
|
||||||
return diff < 0 ? 0 : diff;
|
return diff < 0 ? 0 : diff;
|
||||||
}
|
}
|
||||||
|
bool g_clock12h = false; // app-wide 12-hour clock preference (synced from settings each frame)
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void setClock12h(bool enabled) { g_clock12h = enabled; }
|
||||||
|
bool clock12h() { return g_clock12h; }
|
||||||
|
|
||||||
|
std::string formatClockDateTime(std::int64_t timestamp, bool withSeconds)
|
||||||
|
{
|
||||||
|
if (timestamp <= 0) return {};
|
||||||
|
std::time_t t = static_cast<std::time_t>(timestamp);
|
||||||
|
std::tm* tm = std::localtime(&t); // UI thread only
|
||||||
|
if (!tm) return {};
|
||||||
|
const char* fmt = g_clock12h
|
||||||
|
? (withSeconds ? "%Y-%m-%d %I:%M:%S %p" : "%Y-%m-%d %I:%M %p")
|
||||||
|
: (withSeconds ? "%Y-%m-%d %H:%M:%S" : "%Y-%m-%d %H:%M");
|
||||||
|
char buf[40];
|
||||||
|
return std::strftime(buf, sizeof(buf), fmt, tm) > 0 ? std::string(buf) : std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string formatClockTime(std::int64_t timestamp, bool withSeconds)
|
||||||
|
{
|
||||||
|
if (timestamp <= 0) return {};
|
||||||
|
std::time_t t = static_cast<std::time_t>(timestamp);
|
||||||
|
std::tm* tm = std::localtime(&t); // UI thread only
|
||||||
|
if (!tm) return {};
|
||||||
|
const char* fmt = g_clock12h
|
||||||
|
? (withSeconds ? "%I:%M:%S %p" : "%I:%M %p")
|
||||||
|
: (withSeconds ? "%H:%M:%S" : "%H:%M");
|
||||||
|
char buf[24];
|
||||||
|
return std::strftime(buf, sizeof(buf), fmt, tm) > 0 ? std::string(buf) : std::string();
|
||||||
|
}
|
||||||
|
|
||||||
std::string formatTimeAgo(std::int64_t timestamp)
|
std::string formatTimeAgo(std::int64_t timestamp)
|
||||||
{
|
{
|
||||||
if (timestamp <= 0) return {};
|
if (timestamp <= 0) return {};
|
||||||
|
|||||||
@@ -14,6 +14,19 @@
|
|||||||
namespace dragonx {
|
namespace dragonx {
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
|
// App-wide clock format (24-hour vs 12-hour). Set once per frame by the App from the global
|
||||||
|
// `time_format` setting (setClock12h); the formatters below read it so a single preference drives
|
||||||
|
// every user-facing timestamp. The Chat tab resolves its own override separately.
|
||||||
|
void setClock12h(bool enabled);
|
||||||
|
bool clock12h();
|
||||||
|
|
||||||
|
// Format an epoch timestamp as a local wall-clock date+time honoring the app clock setting:
|
||||||
|
// 24h -> "YYYY-MM-DD HH:MM[:SS]", 12h -> "YYYY-MM-DD hh:MM[:SS] AM/PM". Empty when ts <= 0.
|
||||||
|
std::string formatClockDateTime(std::int64_t timestamp, bool withSeconds = false);
|
||||||
|
|
||||||
|
// Just the time-of-day portion honoring the clock setting: 24h "HH:MM[:SS]" / 12h "hh:MM[:SS] AM/PM".
|
||||||
|
std::string formatClockTime(std::int64_t timestamp, bool withSeconds = false);
|
||||||
|
|
||||||
// Localized relative time, e.g. "5 minutes ago" (via i18n). Empty when timestamp <= 0.
|
// Localized relative time, e.g. "5 minutes ago" (via i18n). Empty when timestamp <= 0.
|
||||||
std::string formatTimeAgo(std::int64_t timestamp);
|
std::string formatTimeAgo(std::int64_t timestamp);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user