From: Joel Rosdahl Date: Sun, 30 Mar 2025 08:46:48 +0000 (+0200) Subject: refactor: Extract timestamp format to util::format_iso8601_timestamp X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1431b813e73e80ecb2416e8facb47de9b25b003b;p=thirdparty%2Fccache.git refactor: Extract timestamp format to util::format_iso8601_timestamp --- diff --git a/cmake/config.h.in b/cmake/config.h.in index f39a18fc..5e6387ed 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -94,7 +94,7 @@ #cmakedefine HAVE_SYS_MMAN_H // Define if you have the header file. -#cmakedefine HAVE_SYS_SENDFILE_H +#cmakedefine HAVE_SYS_SENDFILE_H // Define if you have the header file. #cmakedefine HAVE_SYS_UTIME_H @@ -122,6 +122,9 @@ // Define if you have the "getpwuid" function. #cmakedefine HAVE_GETPWUID +// Define if you have the "gmtime_r" function. +#cmakedefine HAVE_GMTIME_R + // Define if you have the "localtime_r" function. #cmakedefine HAVE_LOCALTIME_R diff --git a/src/ccache/util/logging.cpp b/src/ccache/util/logging.cpp index 30444027..9cbaf781 100644 --- a/src/ccache/util/logging.cpp +++ b/src/ccache/util/logging.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2002 Andrew Tridgell -// Copyright (C) 2009-2024 Joel Rosdahl and other contributors +// Copyright (C) 2009-2025 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -81,21 +82,11 @@ do_log(std::string_view message, bool bulk) static char prefix[200]; if (!bulk || prefix[0] == '\0') { - char timestamp[100]; - auto now = util::TimePoint::now(); - auto tm = util::localtime(now); - if (tm) { - strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &*tm); - } else { - snprintf(timestamp, - sizeof(timestamp), - "%llu", - static_cast(now.sec())); - } + const auto now = util::TimePoint::now(); snprintf(prefix, sizeof(prefix), "[%s.%06u %-5d] ", - timestamp, + util::format_iso8601_timestamp(now).c_str(), static_cast(now.nsec_decimal_part() / 1000), static_cast(getpid())); } diff --git a/src/ccache/util/string.cpp b/src/ccache/util/string.cpp index 54874ffb..b19d3aae 100644 --- a/src/ccache/util/string.cpp +++ b/src/ccache/util/string.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -185,6 +186,23 @@ format_human_readable_size(uint64_t size, SizeUnitPrefixType prefix_type) } } +std::string +format_iso8601_timestamp(const TimePoint& time, TimeZone time_zone) +{ + char timestamp[100]; + const auto tm = + (time_zone == TimeZone::local ? util::localtime : util::gmtime)(time); + if (tm) { + strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", &*tm); + } else { + snprintf(timestamp, + sizeof(timestamp), + "%llu", + static_cast(time.sec())); + } + return timestamp; +} + tl::expected parse_double(const std::string& value) { diff --git a/src/ccache/util/string.hpp b/src/ccache/util/string.hpp index f78ee085..219b1c34 100644 --- a/src/ccache/util/string.hpp +++ b/src/ccache/util/string.hpp @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include @@ -40,6 +41,7 @@ namespace util { // --- Interface --- enum class SizeUnitPrefixType { binary, decimal }; +enum class TimeZone { local, utc }; // Return true if `suffix` is a suffix of `string`. bool ends_with(std::string_view string, std::string_view suffix); @@ -81,6 +83,10 @@ std::string format_human_readable_diff(int64_t diff, std::string format_human_readable_size(uint64_t size, SizeUnitPrefixType prefix_type); +// Format `time` as a human-readable ISO8601 timestamp string. +std::string format_iso8601_timestamp(const TimePoint& time, + TimeZone time_zone = TimeZone::local); + // Join stringified elements of `container` delimited by `delimiter` into a // string. There must exist an `std::string to_string(T::value_type)` function. template diff --git a/src/ccache/util/time.cpp b/src/ccache/util/time.cpp index e0ab7eeb..26868734 100644 --- a/src/ccache/util/time.cpp +++ b/src/ccache/util/time.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2023 Joel Rosdahl and other contributors +// Copyright (C) 2023-2025 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -20,6 +20,24 @@ namespace util { +std::optional +gmtime(std::optional time) +{ + time_t timestamp = time ? time->sec() : TimePoint::now().sec(); +#ifdef HAVE_GMTIME_R + struct tm result; + if (gmtime_r(×tamp, &result)) { + return result; + } +#else + struct tm* result = ::gmtime(×tamp); + if (result) { + return *result; + } +#endif + return std::nullopt; +} + std::optional localtime(std::optional time) { diff --git a/src/ccache/util/time.hpp b/src/ccache/util/time.hpp index 938b691a..635faad3 100644 --- a/src/ccache/util/time.hpp +++ b/src/ccache/util/time.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2023-2024 Joel Rosdahl and other contributors +// Copyright (C) 2023-2025 Joel Rosdahl and other contributors // // See doc/AUTHORS.adoc for a complete list of contributors. // @@ -25,6 +25,10 @@ namespace util { +// Thread-safe version of `gmtime(3)`. If `time` is not specified the current +// time of day is used. +std::optional gmtime(std::optional time = {}); + // Thread-safe version of `localtime(3)`. If `time` is not specified the current // time of day is used. std::optional localtime(std::optional time = {}); diff --git a/unittest/test_util_string.cpp b/unittest/test_util_string.cpp index 25fbb8b8..6d98f83d 100644 --- a/unittest/test_util_string.cpp +++ b/unittest/test_util_string.cpp @@ -274,6 +274,17 @@ TEST_CASE("util::format_human_readable_size") } } +TEST_CASE("util::format_iso8601_timestamp") +{ + using util::TimePoint; + using util::TimeZone; + + CHECK(util::format_iso8601_timestamp(TimePoint(0), TimeZone::utc) + == "1970-01-01T00:00:00"); + CHECK(util::format_iso8601_timestamp(TimePoint(1234567890), TimeZone::utc) + == "2009-02-13T23:31:30"); +} + TEST_CASE("util::join") { {