There's a serious problem here:
gettimeofday(&curTime, NULL);
⋮
time(&rawtime);
Suppose the system time is approximately HH:MM:00.999 when curTime
is assigned, but a few microseconds later at HH:MM:01.000 when rawtime
is assigned. This means that we'll print HH:MM:01.999, which is quite far from either value.
Swapping the two calls won't help - that would result in HH:MM:00.000, which is also wrong. We need to get a single precise value, and use that for the whole of the formatting.
Instead of writing out %Y-%m-%d
and %H:%M:%S
, it's easier and arguably clearer to use the shorter forms %F
and %T
. And we can use the return value from std::strftime()
to determine the position at which the fractional seconds should be formatted.
We can use the size of the longest expected output to determine how large the buffer needs to be:
char buffer[sizeof "9999-12-31 23:59:59.999"];
In modern C++, we would use std::chrono
for time access, rather than the C library:
#include <chrono>
#include <iostream>
int main()
{
using namespace std::chrono;
auto timepoint = system_clock::now();
auto coarse = system_clock::to_time_t(timepoint);
auto fine = time_point_cast<std::chrono::milliseconds>(timepoint);
char buffer[sizeof "9999-12-31 23:59:59.999"];
std::snprintf(buffer + std::strftime(buffer, sizeof buffer - 3,
"%F %T.", std::localtime(&coarse)),
4, "%03lu", fine.time_since_epoch().count() % 1000);
std::cout << buffer << '\n';
}
If you have a C++ environment that implements C++20's std::format
, then it becomes much, much simpler:
#include <chrono>
#include <format>
#include <iostream>
// UNTESTED!!
int main()
{
auto timepoint = std::chrono::system_clock::now();
auto buffer = std::format("%F %R:%06.3S", timepoint.time_since_epoch());
std::cout << buffer << '\n';
}
I'm not yet sure whether we can supply a precision specifier with %T
conversion, so I split the time representation. I may try that out when I have access to a GCC with sufficient support.
%03d
to formatmilli
so you get leading zeros. And since your format is so close to ISO-8601, you might want to continue with it and use "." instead of ":" to separate the seconds and milliseconds. \$\endgroup\$