Utility::FormatDateTime(): provide an overload for tm*

This allows the function to be used both with a double timestamp or a pointer
to a tm struct. With this, a similar implementation inside the tests can simply
use our regular function.
This commit is contained in:
Julian Brost 2024-08-21 12:31:44 +02:00
parent d5b3ffaa6d
commit 39ae2e8ca4
3 changed files with 28 additions and 32 deletions

View File

@ -1051,8 +1051,31 @@ String Utility::FormatDuration(double duration)
return NaturalJoin(tokens);
}
String Utility::FormatDateTime(const char *format, double ts)
String Utility::FormatDateTime(const char* format, double ts)
{
// Sub-second precision is removed, strftime() has no format specifiers for that anyway.
auto tempts = boost::numeric_cast<time_t>(ts);
tm tmthen;
#ifdef _MSC_VER
errno_t err = localtime_s(&tmthen, &tempts);
if (err) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("localtime_s")
<< boost::errinfo_errno(err));
}
#else /* _MSC_VER */
if (!localtime_r(&tempts, &tmthen)) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("localtime_r")
<< boost::errinfo_errno(errno));
}
#endif /* _MSC_VER */
return FormatDateTime(format, &tmthen);
}
String Utility::FormatDateTime(const char* format, const tm* t) {
/* Known limitations of the implementation: Only works if the result is at most 127 bytes, otherwise returns an
* empty string. An empty string is also returned in all other error cases as proper error handling for strftime()
* is impossible.
@ -1074,25 +1097,6 @@ String Utility::FormatDateTime(const char *format, double ts)
* the error was due to the buffer being too small.
*/
// Sub-second precision is removed, strftime() has no format specifiers for that anyway.
auto tempts = boost::numeric_cast<time_t>(ts);
tm tmthen;
#ifdef _MSC_VER
errno_t err = localtime_s(&tmthen, &tempts);
if (err) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("localtime_s")
<< boost::errinfo_errno(err));
}
#else /* _MSC_VER */
if (!localtime_r(&tempts, &tmthen)) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("localtime_r")
<< boost::errinfo_errno(errno));
}
#endif /* _MSC_VER */
#ifdef _MSC_VER
/* On Windows, the strftime() function family invokes an invalid parameter handler when the format string is
* invalid (see the "Remarks" section in their documentation). std::put_time() shows the same behavior as it
@ -1120,7 +1124,7 @@ String Utility::FormatDateTime(const char *format, double ts)
#endif /* _MSC_VER */
char buf[128];
size_t n = strftime(buf, sizeof(buf), format, &tmthen);
size_t n = strftime(buf, sizeof(buf), format, t);
// On error, n == 0 and an empty string is returned.
return std::string(buf, n);
}

View File

@ -77,7 +77,8 @@ public:
static String Join(const Array::Ptr& tokens, char separator, bool escapeSeparator = true);
static String FormatDuration(double duration);
static String FormatDateTime(const char *format, double ts);
static String FormatDateTime(const char* format, double ts);
static String FormatDateTime(const char* format, const tm* t);
static String FormatErrorNumber(int code);
#ifndef _WIN32

View File

@ -527,16 +527,7 @@ struct Segment
std::string pretty_time(const tm& t)
{
#if defined(__GNUC__) && __GNUC__ < 5
// GCC did not implement std::put_time() until version 5
char buf[128];
size_t n = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", &t);
return std::string(buf, n);
#else /* defined(__GNUC__) && __GNUC__ < 5 */
std::ostringstream stream;
stream << std::put_time(&t, "%Y-%m-%d %H:%M:%S %Z");
return stream.str();
#endif /* defined(__GNUC__) && __GNUC__ < 5 */
return Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %Z", &t);
}
std::string pretty_time(time_t t)