2010-03-09 4 views
22

struct timeval 인스턴스를 "2010-01-01 15 : 35 : 10.0001"과 같이 사람이 읽을 수있는 형식으로 포맷하는 방법을 알려주십시오.인쇄 가능한 형식의 구조 timeval

+2

중복 된 http://stackoverflow.com/questions/1469495/unix-programming-struct-timeval-how-to-print-it-c-programming? –

+6

dup이 아니기 때문에 사람이 읽을 수있는 형식을 지정하고 stftime을 가리키며 다른 하나는 초와 useconds 만 추출합니다. –

답변

13

strftime을 사용하여 변환 한 다음 tv_usec 부분을 추가하십시오.

1

strftime 함수를 사용하여 날짜와 시간을 문자열로 변환 할 수 있습니다.

55

strftime()가 다루는 struct tm에 있지 않으므로 수동으로 마이크로 초 부분을 추가해야합니다. 우리가 제로 채워진 마이크로 필드를 얻을 수 06의 명시적인 정밀도를 사용하는 방법

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); 

참고 : 여기에 조각입니다. 마이크로 초는 0에서 999,999까지이므로 항상 6 자리로 채워야합니다. 예를 들어 57 마이크로 초를 570,000으로 나타냅니다 ("1.57"vs "1.000057"비교).

+1

이것은 strftime (반환 바이트 수를 반환)의 반환 값을 저장하고 snprintf로 전달할 수있는 동일한 버퍼에 인덱스하기 위해 사용함으로써보다 효율적으로 수행 될 수 있습니다. 이것은 하나의 버퍼를 사용하고 strftime()에서 문자열의 추가 사본을 피할 것이다. –

+2

매우 유용한 답과 일반적으로이 모든 스레드. 마지막 줄에서'', % s. % 06ld "'를 지정하는 것이 더 나을 것입니다. 감사합니다. – lrleon

+1

경고 : 형식 '% d'은 'int'형식의 인수를 필요로하지만 인수 5는 마지막 줄에서 '__suseconds_t {일명 long int}'[-Wformat =] 형식을 가지고 있습니다. ? – bakalolo

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

나는이 코드를 찾고 있다고 생각합니다.

1

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

대신의 현지의 localtime_s를 사용하여 tv_sec가 변환, 당신이 만약 때문에 전역 함수를 작성 중이므로 문제가 발생할 수 있습니다. 함수는 다중 스레드 솔루션에서 작동 할 수있는 경우 다음이 내가 무엇을 사용 localtime_r

0

사용을 고려하십시오 :

#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입니다.

관련 문제