格式化结构timespec

格式化结构timespec,c,linux,gcc,C,Linux,Gcc,如何将struct timespec格式化为字符串?此结构由Linux gcc上的clock\u gettime()返回: struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; 您可以使用std::stringstream。您可以将任何内容流式传输到其中: std::stringstream stream; stream <&

如何将
struct timespec
格式化为字符串?此结构由Linux gcc上的
clock\u gettime()
返回:

struct timespec {
    time_t   tv_sec;        /* seconds */
    long     tv_nsec;       /* nanoseconds */
};

您可以使用std::stringstream。您可以将任何内容流式传输到其中:

std::stringstream stream;
stream << 5.7;
stream << foo.bar;

std::string s = stream.str();
std::stringstream;

stream您可以将tv_sec参数传递给某些格式化函数。看看gmtime,localtime()。然后看看snprintf

格式化它的一种方法是:

printf("%lld.%.9ld", (long long)ts.tv_sec, ts.tv_nsec);

我想问同样的问题。下面是我当前获得如下字符串的解决方案:
2013-02-07 09:24:40.749355372
我不确定是否有比这更直接的解决方案,但至少字符串格式可以通过这种方法自由配置

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

#define NANO 1000000000L

// buf needs to store 30 characters
int timespec2str(char *buf, uint len, struct timespec *ts) {
    int ret;
    struct tm t;

    tzset();
    if (localtime_r(&(ts->tv_sec), &t) == NULL)
        return 1;

    ret = strftime(buf, len, "%F %T", &t);
    if (ret == 0)
        return 2;
    len -= ret - 1;

    ret = snprintf(&buf[strlen(buf)], len, ".%09ld", ts->tv_nsec);
    if (ret >= len)
        return 3;

    return 0;
}

int main(int argc, char **argv) {
    clockid_t clk_id = CLOCK_REALTIME;
    const uint TIME_FMT = strlen("2012-12-31 12:59:59.123456789") + 1;
    char timestr[TIME_FMT];

    struct timespec ts, res;
    clock_getres(clk_id, &res);
    clock_gettime(clk_id, &ts);

    if (timespec2str(timestr, sizeof(timestr), &ts) != 0) {
        printf("timespec2str failed!\n");
        return EXIT_FAILURE;
    } else {
        unsigned long resol = res.tv_sec * NANO + res.tv_nsec;
        printf("CLOCK_REALTIME: res=%ld ns, time=%s\n", resol, timestr);
        return EXIT_SUCCESS;
    }
}

以下内容将返回符合ISO8601和RFC3339的UTC时间戳,包括纳秒

它使用
strftime()
,它与
struct timespec
一起工作,与
struct timeval
一起工作,因为它所关心的只是秒数,两者都提供秒数。然后添加纳秒(注意用零填充!)以及UTC后缀“Z”

输出示例:
2021-01-19T04:50:01.435561072Z

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

int utc_system_timestamp(char[]);

int main(void) {
    char buf[31];
    utc_system_timestamp(buf);
    printf("%s\n", buf);
}

// Allocate exactly 31 bytes for buf
int utc_system_timestamp(char buf[]) {
    const int bufsize = 31;
    const int tmpsize = 21;
    struct timespec now;
    struct tm tm;
    int retval = clock_gettime(CLOCK_REALTIME, &now);
    gmtime_r(&now.tv_sec, &tm);
    strftime(buf, tmpsize, "%Y-%m-%dT%H:%M:%S.", &tm);
    sprintf(buf + tmpsize -1, "%09luZ", now.tv_nsec);
    return retval;
}

这取决于您希望字符串的外观。另外,不要同时使用
c++
c
标记。用你正在使用的语言标记,你使用的是C++还是C?此外,你说的格式是什么意思?您需要指定所需的outputformat(由于epoch是微不足道的,所以秒数可能更难,具体取决于它应该是什么样子)。-1:不,您不能只是“将任何内容流到其中”;适当的
运算符必须是
len-=ret-1?为什么
len-=ret不好?可以使用sizeof代替strlen。同样愚蠢,但编译时已解决。ret>=len之间的比较是有符号与无符号的。微小的更改。@russoue老实说,我不记得了,但我想是因为我计算时没有包含在返回值
strftime
中的尾随
\0
。sizeof(str)-1将给出相同的结果-尽管您在那里添加了1,因此sizeof将替换完整的表达式。我的评论相当讽刺:p这很有效,但我很好奇为什么选择了%.9ld,而不是像%09ld这样更简单的东西?@Zectbumo:问题在于你是否认为它是打印一个小数位数最少的整数,还是将转换后的整数用零字符填充到最小的字段宽度。虽然这从技术上回答了OP的问题(因为没有指定格式),但大多数程序员希望得到比秒数和纳秒数的文本打印输出更可读的内容。例如,如果timespec值表示日历日期和时间,则时间戳格式更可取,而对于经过的时间,最有用的是将其分解为小时、分钟、秒和纳秒(例如)。一个完整的答案将解决这些用途。
sprintf(buf,“%s%09luZ”,buf,now.tv\u nsec)是未定义的行为,目标缓冲区不能与任何其他参数重叠<代码>sprintf(buf+strlen(buf),“%09luZ”,now.tv\u nsec)是一条路。@mch:事实上,这违反了C99§7.19.6.5的规定,
如果复制发生在重叠的对象之间,则行为是未定义的。
已修复。”。谢谢你的合作。
#include <stdio.h>
#include <time.h>
#include <sys/time.h>

int utc_system_timestamp(char[]);

int main(void) {
    char buf[31];
    utc_system_timestamp(buf);
    printf("%s\n", buf);
}

// Allocate exactly 31 bytes for buf
int utc_system_timestamp(char buf[]) {
    const int bufsize = 31;
    const int tmpsize = 21;
    struct timespec now;
    struct tm tm;
    int retval = clock_gettime(CLOCK_REALTIME, &now);
    gmtime_r(&now.tv_sec, &tm);
    strftime(buf, tmpsize, "%Y-%m-%dT%H:%M:%S.", &tm);
    sprintf(buf + tmpsize -1, "%09luZ", now.tv_nsec);
    return retval;
}
gcc foo.c -o foo -lrt