ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C/C++ localtime 함수로 현재 시간 출력하기
    C and C++ 2019. 12. 8. 23:40

    윈도우에서는 서비스나 독립된 exe 형태로 구동되고, 
    리눅스에서는 데몬으로 구동되는 UI가 없는 형태의 네이티브 모듈을 만들고 있었다.
    그런데 모듈에 필요한 기능 중 현재의 시간을 구해 계산할 필요가 있는 부분이 나타났다.

    OS 플랫폼마다 시간을 구하는 방법은 다양하지만, 
    되도록 양쪽 플랫폼에서 모두 사용 가능한 하나의 코드베이스를 유지하는 기조를 가지고 있었다.
    그리고 마이크로 세컨드 단위의 정확한 시간이 필요한 것은 아니어서, 
    웬만하면 오픈소스 라이브러리를 가져다 쓰지 않고 해결하고 싶기도 했다.

    이 조건을 만족하는 함수가 다행히 C의 기본 라이브러리에 있었는데 localtime함수가 그것이다.
    리눅스 링크는 여기에서 찾을 수 있으며, 윈도우 링크는 여기에서 찾을 수 있다.

    사용 방법은 아주 간단한데, 
    다음 과정을 통해 현재 시간을 YYYY-MM-DDTHH:MM:SS의 표준 형태로 나타낼 수 있다.

    1. time.h 
    time 관련 함수가 정의된 time.h를 소스코드에 포함한다.

    #include  <time.h>

     

    윈도우나 리눅스 모두에서 기본적으로 제공되는 함수들로 특별한 제한 없이 사용이 가능하다.

    2. time() 호출로 현재의 시간을 획득
    time(NULL)함수를 호출하여 현재의 시간을 가져온다.

    time_t curTime = time(NULL);

     

    time 함수는 time_t 타입의 결과를 돌려주는데, 
    이 결과는 1970년 1월 1일 0시 0분 0초를 기점으로 현재까지 흐른 시간을 초단위로 나타낸다.

    3. localtime() 호출로 포맷 변환하기
    time 함수가 돌려주는 time_t의 값은 시스템에 따라 32비트나 64비트 정수이다.
    이 값을 다음과 같이 localtime 함수를 이용해 사용하기 쉬운 형태로 변환한다.

    struct tm *pLocal = localtime(&curTime);

     

    호출이 성공적일 경우 pLocal은 변환 결과를 가리키는 포인터이다.
    실패할 경우 pLocal은 NULL이 되며, 에러 원인은 errno를 통해 확인이 가능하다.

    4. 출력
    struct tm 구조체는 다음과 같은 멤버들을 포함한다.

    멤버 설명 값 범위
    tm_year 1900년 이후 몇 년이 지났는지 현재 년도 - 1900
    tm_mon 현재 월 0~11
    tm_yday 1년중 몇 일

    0~365

    1월 1일 = 0

    윤년(leap year)일 경우 12월 31일 = 365

    tm_mday 1달 중 몇 일 1~31
    tm_wday 현재 요일

    0~6

    일요일 = 0

    tm_hour 현재 시간 0~23
    tm_min 현재 분 0~59
    tm_sec 현재 초

    0~60

    윤초(leap second)일 경우 = 60

    tm_isdst 섬머타임 실시 여부

    실시 중이면 > 0

    미실시이면 = 0

    실시 정보가 없으면 < 0


    다음 코드를 통해 목적한 형태의 시간 스트링을 출력 가능하다.

    printf("%04d-%02d-%02dT%02d:%02d:%02d",  
        pLocal->tm_year + 1900, pLocal->tm_mon + 1, pLocal->tm_mday,  
        pLocal->tm_hour, pLocal->tm_min, pLocal->tm_sec);


    * 주의사항
    localtime()은 struct tm 의 결과 포인터를 반환한다.
    모양에서 유추되는 것처럼 localtime은 기본적으로 thread safe하지 않은 함수이다.

    리눅스의 경우에는 localtime_r()이라는 스레드 대응 버전을 사용할 수 있다.

    그러나 윈도우의 경우에는 이 변경 버전이 제공되지 않는데, 
    localtime이 내부적으로 thread safe한 형태로 구현이 되어 있는 것으로 유추된다.
    MSDN에 나온 것은 아니지만 복수의 커멘트에서 그렇다고 한다.

    다음은 주의사항을 반영한 전체 소스 코드이다.

    #include <time.h>
    
    int PrintCurrentTime(void) 
    { 
        // Get the current time 
        time_t curTime = time(NULL); 
    
        // Convert the current time 
        struct tm *pLocal = NULL; 
    #if defined(_WIN32) || defined(_WIN64) 
        pLocal = localtime(&curTime); 
    #else 
        localtime_r(&curTime, pLocal); 
    #endif 
        if (pLocal == NULL) 
        { 
            // Failed to convert the current time 
            return 1; 
        } 
    
        // Print the current time 
        printf("%04d-%02d-%02dT%02d:%02d:%02d",  
            pLocal->tm_year + 1900, pLocal->tm_mon + 1, pLocal->tm_mday,  
            pLocal->tm_hour, pLocal->tm_min, pLocal->tm_sec); 
    
        // Return success 
        return 0; 
    } 



    Fin.

    반응형

    댓글

Calvin's Memo