Skip to content

Commit

Permalink
Utility::FormatDateTime(): provide an overload for tm*
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
julianbrost authored and Al2Klimov committed Sep 19, 2024
1 parent 733ea50 commit 771c2e7
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 32 deletions.
46 changes: 25 additions & 21 deletions lib/base/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/base/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ class Utility
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
Expand Down
11 changes: 1 addition & 10 deletions test/icinga-legacytimeperiod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 771c2e7

Please sign in to comment.