Linux 将 timeval 结构化为可打印格式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2408976/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:50:39  来源:igfitidea点击:

Struct timeval to printable format

clinux

提问by marxin

Could you please help me how to format a struct timevalinstance to human readable format like "2010-01-01 15:35:10.0001"?

你能帮我如何将struct timeval实例格式化为人类可读的格式,比如“2010-01-01 15:35:10.0001”?

采纳答案by Didier Trosset

Convert the tv_secusing localtime, and strftime, then append tv_usecpart.

转换tv_secusing localtime, and strftime,然后附加tv_usec部分。

回答by Frerich Raabe

You can use the strftimefunction to convert a date and time to a string.

您可以使用strftime函数将日期和时间转换为字符串。

回答by unwind

You need to manually append the microseconds part, since it's not in the struct tmthat strftime() deals with. Here's a snippet:

您需要手动附加微秒部分,因为它不在struct tmthat strftime() 处理中。这是一个片段:

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 06to 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").

请注意我们如何使用显式精度 of06来获得零填充的微秒字段。由于微秒从 0 到 999,999,因此必须始终填充为 6 位数字。我们不想将例如 57 微秒误表示为 570,000(比较“1.57”与“1.000057”)。

回答by Luo Hongshuai

ctime((const time_t *) &timeval.ts.tv_sec)

I think you are looking for this code, just for your reference.

我认为您正在寻找此代码,仅供参考。

回答by Joe Hildebrand

Combining previous answers and comments, changing the format to be RFC3339-compliant, and checking all of the error conditions, you get this:

结合以前的答案和评论,将格式更改为符合RFC3339并检查所有错误条件,您会得到:

#include <stdio.h>
#include <sys/time.h>

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 < sz))
    {
      int w = snprintf(buf+written, sz-(size_t)written, ".%06dZ", tv->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;
}

回答by Behrang

Convert the tv_sec using localtime_sinstead 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

使用localtime_s而不是 localtime转换 tv_sec ,因为如果您正在编写全局函数,它可能会导致一些问题。如果您的函数可以在多线程解决方案中工作,那么请考虑使用localtime_r

回答by a3f

This is what I use:

这是我使用的:

#include <time.h>
#include <string.h>

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#define gmtime_r(ptime,ptm) (gmtime_s((ptm),(ptime)), (ptm))
#else
#include <sys/time.h>
#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 < 6; i++) usecs /= 10;
        char *spaces = frac + sprintf(frac - 1, ".%-*luZ", precision, usecs) - 3;
        if (spaces > frac) while (*spaces == ' ') *spaces-- = '0';
    }

    return iso8601;
}

precisionspecifies the width of the seconds fraction. Code is y10k- and yINT_MAX-proof.

precision指定秒部分的宽度。代码是 y10k- 和 y-proof INT_MAX