
1. time_t 소개
C++ 에서는 UTC 1970년 1월 1일 00:00:00로부터 시간을 초(second)단위로 카운트하여 time_t 라는 타입으로 제공한다. (time_t 타입은 int64 를 typedef 으로 정의하고 있다.)
즉, 1970년 1월 1일 자정을 기준으로 시스템의 타임 서비스에서 가져온 time_t 값은 0이며 이후 초당 1씩 추가로 카운트 된다.
이 외에 time_t 형식을 년월일시분초 형태로 분할한 일시(struct tm 형식)로 변환하는 gmtime(gmtime_s)과 localtime(localtime_s) 함수가 있다.
또한 struct tm 형식을 time_t 형식으로 변환하는 mktime(_mkgmtime, timegm)이 있다.
2. tm 구조체
위에서 설명한 tm 구조체는 1970년 1월 1일 자정 이후로 누적된 초(second) 를 표현하는 time_t 의 경우 컴퓨터가 아닌 사람이 직접 사용하기에는 매우 불편하다.
struct tm 의 경우 년월일시분초 단위로 멤버변수를 가지고 있어 실제로 사람이 사용하는 날짜의 개념을 적용한 구조체 이다.
struct tm | |
{ | |
int tm_sec; // seconds after the minute - [0, 60] including leap second | |
int tm_min; // minutes after the hour - [0, 59] | |
int tm_hour; // hours since midnight - [0, 23] | |
int tm_mday; // day of the month - [1, 31] | |
int tm_mon; // months since January - [0, 11] | |
int tm_year; // years since 1900 | |
int tm_wday; // days since Sunday - [0, 6] | |
int tm_yday; // days since January 1 - [0, 365] | |
int tm_isdst; // daylight savings time flag | |
}; |
사용자가 이 tm 구조체를 원하는 날짜와 시간으로 채워서 타임 시스템 함수들에 인자로 전달해 주면 컴퓨터가 사용하는 time_t 값으로 전환 할 수 있으며 반대의 경우도 가능하다.
3. time_t -> struct tm
time_t 로 가져온 현재 시간을 tm 구조체로 변경 합니다.
gmtime(gmtime_s) 과 localtime(localtime_s) 함수를 통해 각각 UTC(세계협정시) 나 시스템의 타임존에 맞는 시간으로 바꿀 수 있다.
현재 MS Visual C++ 2019 기준으로 gmtime 과 localtime 은 deprecate 되었으며 버퍼 배열을 사용하는 gmtime_s 와 localtime_s 를 사용해야 한다.
include <iostream> | |
include <stdio.h> | |
include <time.h> | |
int main() | |
{ | |
time_t curTime; | |
time(&curTime); //현재 시스템의 시간에 해당하는 time_t 값을 가져옴) | |
////////////////////////////////////////////////////// | |
//현재 시스템의 타임존 기준(local time) 가져오기 | |
////////////////////////////////////////////////////// | |
struct tm localTM; | |
localTime_s(&localTM, &curTime); //time_t -> struct tm | |
char buff[256]; | |
asctime_s(buff, sizeof(localBuff), &localTM); //struct tm 을 문자열로 바꿔줌. | |
printf("tm : %s\n", buff); //"Mon Mar 30 12:00:00 2020" | |
////////////////////////////////////////////////////// | |
//UTC 기준 시간(GMT) 정보 time_t 가져오기 | |
////////////////////////////////////////////////////// | |
struct tm gmTM; | |
gmtime_s(&gmTM, &curTime); //time_t -> struct tm | |
asctime_s(buff, sizeof(buff), &gmTM); //struct tm 을 문자열로 바꿔줌. | |
printf("tm : %s\n", buff); //"Mon Mar 30 03:00:00 2020" | |
} |
4. struct tm -> time_t
반대로 사용자가 tm 구조체에 원하는 날짜와 시간을 입력한 후 컴퓨터가 사용하는 time_t 로 변환 하는것도 가능하다.
다만 어째서인지 C/C++ 표준 라이브러리에는 시스템이 속한 타임존의 시간인 local time 으로 바꾸는 함수인 mktime 은 존재 하지만 UTC(세계협정시) tm 구조체를 time_t 로 바꾸는 함수는 지원하지 않는다.
어쩔 수 없이 비표준 함수를 찾아봤는데 유닉스 기반 시스템에서는 timegm 함수를, MS Visual C++ 에서는 _mkgmtime 함수를 사용할 수 있다.
아래 예제에서는 MS Visual C++ 기반의 _mkgmtime 을 사용했다.
#include <iostream> | |
#include <stdio.h> | |
#include <time.h> | |
time_t MakeLocalTime_t(int YYYY, int MM, int DD, int hh, int mi, int ss); //현지 시각 tm -> time_t | |
time_t MakeUTCTime_t(int YYYY, int MM, int DD, int hh, int mi, int ss); //UTC(GMT) 시각 tm -> time_t | |
int main() | |
{ | |
//time_t 값으로 변환할 날짜 | |
int year = 2020; | |
int mon = 12; | |
int day = 25; | |
int hour = 0; | |
int min = 0; | |
int sec = 0; | |
time_t localTime = MakeLocalTime_t(year, mon, day, hour, min, sec); | |
printf("2020 x-mas local time_t : %n\n", localTime); | |
time_t utcTime = MakeUTCTime_t(year, mon, day, hour, min, sec); | |
printf("2020 x-mas UTC time_t : %n\n", utcTime); | |
//////////////////////////////////////////////////// | |
//응용 | |
//////////////////////////////////////////////////// | |
//현재부터 2020년 크리스마스 까지 남은 초 | |
time_t curTime; | |
time(&curTime); | |
printf("time remaining until 2020 x-mas : %n\n", localTime - curTime); | |
//2020년 크리스마스 이후인지 검사 | |
if (curTime >= localTime) | |
{ | |
printf("Merry X-mas"); | |
} | |
} | |
time_t MakeLocalTime_t(int YYYY, int MM, int DD, int hh, int mi, int ss) | |
{ | |
struct tm st_tm; | |
st_tm.tm_year = YYYY - 1900; | |
st_tm.tm_mon = MM - 1; | |
st_tm.tm_mday = DD; | |
st_tm.tm_hour = hh; | |
st_tm.tm_min = mi; | |
st_tm.tm_sec = ss; | |
return mktime( &st_tm ); | |
} | |
time_t MakeUTCTime_t(int YYYY, int MM, int DD, int hh, int mi, int ss) | |
{ | |
struct tm st_tm; | |
st_tm.tm_year = YYYY - 1900; | |
st_tm.tm_mon = MM - 1; | |
st_tm.tm_mday = DD; | |
st_tm.tm_hour = hh; | |
st_tm.tm_min = mi; | |
st_tm.tm_sec = ss; | |
return _mkgmtime( &st_tm ); | |
} |
보통 서비스 중에 특정 날짜, 시간에 자동 실행되야 하는 이벤트 등의 경우 미리 필요한 날짜를 time_t 값으로 구해서 테이블에 넣어두고 현재 time_t 값과 비교하면서 체크 하는 방식으로 자주 사용되곤 한다.
댓글