Подтвердить что ты не робот

Struct timeval для печати

Не могли бы вы помочь мне отформатировать экземпляр struct timeval в формате для чтения, например "2010-01-01 15: 35: 10.0001"?

4b9b3361

Ответ 1

Преобразуйте tv_sec с помощью localtime и strftime, затем добавьте часть tv_usec.

Ответ 2

Вам нужно вручную добавить часть микросекунд, так как она не находится в struct tm, с которой работает 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);

Обратите внимание на то, что мы используем явную точность 06 для получения поля с нулевыми значениями микросекунд. Поскольку микросекунды идут от 0 до 999,999, он всегда должен быть дополнен до 6 цифр. Мы не хотим искажать, например. 57 микросекунд как 570 000 (сравните "1,57" против "1.000057" ).

Ответ 3

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

Я думаю, что вы ищете этот код, просто для справки.

Ответ 4

Вы можете использовать функцию strftime для преобразования даты и времени в строку.

Ответ 5

Объединяя предыдущие ответы и комментарии, изменяя формат RFC3339 -compliant и проверяя все условия ошибки, вы получаете это

#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;
}

Ответ 6

Преобразуйте tv_sec, используя localtime_s вместо localtime, потому что, если вы пишете глобальную функцию, это может вызвать некоторые проблемы. если ваша функция может работать в многопоточном решении, пожалуйста, рассмотрите возможность использования localtime_r

Ответ 7

Это то, что я использую:

#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;
}

precision указывает ширину доли секунд. Код - y10k- и y INT_MAX -защищенный.