Could you please help me how to format a struct timeval
instance to human readable format like "2010-01-01 15:35:10.0001"?
问题:
回答1:
Convert the tv_sec
using localtime
, and strftime
, then append tv_usec
part.
回答2:
You need to manually append the microseconds part, since it's not in the struct tm
that strftime
() deals with. Here's a snippet:
struct timeval tv; time_t nowtime; struct tm *nowtm; char tmbuf[64], buf[64]; gettimeofday(&tv, NULL); nowtime = tv.tv_sec; nowtm = localtime(&nowtime); strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm); snprintf(buf, sizeof buf, "%s.%06ld", tmbuf, tv.tv_usec);
Note how we use explicit precision of 06
to get a zero-filled microseconds field. Since the microseconds go from 0 to 999,999, it must always be padded to 6 digits. We don't want to misrepresent e.g. 57 microseconds as 570,000 (compare "1.57" vs "1.000057").
回答3:
ctime((const time_t *) &timeval.ts.tv_sec)
I think you are looking for this code, just for your reference.
回答4:
You can use the strftime function to convert a date and time to a string.
回答5:
Combining previous answers and comments, changing the format to be RFC3339-compliant, and checking all of the error conditions, you get this:
#include #include ssize_t format_timeval(struct timeval *tv, char *buf, size_t sz) { ssize_t written = -1; struct tm *gm = gmtime(&tv->tv_sec); if (gm) { written = (ssize_t)strftime(buf, sz, "%Y-%m-%dT%H:%M:%S", gm); if ((written > 0) && ((size_t)written tv_usec); written = (w > 0) ? written + w : -1; } } return written; } int main() { struct timeval tv; char buf[28]; if (gettimeofday(&tv, NULL) != 0) { perror("gettimeofday"); return 1; } if (format_timeval(&tv, buf, sizeof(buf)) > 0) { printf("%s\n", buf); // sample output: // 2015-05-09T04:18:42.514551Z } return 0; }
回答6:
Convert the tv_sec using localtime_s instead of localtime, because if you are writing a global function it may cause some problems. if your function may work in a multi-threaded solution then please consider using localtime_r
回答7:
This is what I use:
#include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include #define gmtime_r(ptime,ptm) (gmtime_s((ptm),(ptime)), (ptm)) #else #include #endif #define ISO8601_LEN (sizeof "1970-01-01T23:59:59.123456Z") char *timeval_to_str(char iso8601[restrict static ISO8601_LEN], unsigned precision, const struct timeval * restrict tv) { struct tm tm; if (!gmtime_r(&tv->tv_sec, &tm)) return memcpy(iso8601, "Error: Year overflow", sizeof "Error: Year overflow"); tm.tm_year %= 10*1000; char *frac = iso8601 + strftime(iso8601, sizeof "1970-01-01T23:59:59.", "%Y-%m-%dT%H:%M:%SZ", &tm); if (precision) { unsigned long usecs = tv->tv_usec; for (int i = precision; i frac) while (*spaces == ' ') *spaces-- = '0'; } return iso8601; }
precision
specifies the width of the seconds fraction. Code is y10k- and yINT_MAX
-proof.