학습자료(~2017)/C,C++

시간 (time) 함수에 대한 고찰 mktime , strptime, time zone , UTC , KST

단세포소년 2013. 4. 15. 20:32
반응형

시간 함수를 사용하면서 가장 힘들었던 점은 UTC , GMT 와 timezone 에 따른 시간의 편차이다.

1970년 01월 01일 00시 00분 00초 를 기점으로 흐르는 시간을 epoch time 이라고 한다.

바꾸어 말하면 0 epoch time 은 1970년 01월 01일 00시 00분 00초 이다.


strptime 함수는 날짜와 시간으로 이루어진 문자열을 struct tm 이라는 구조체로 바꾼다.

 struct tm

{

  int tm_sec; /* Seconds. [0-60] (1 leap second) */

  int tm_min; /* Minutes. [0-59] */

  int tm_hour; /* Hours. [0-23] */

  int tm_mday; /* Day. [1-31] */

  int tm_mon; /* Month. [0-11] */

  int tm_year; /* Year - 1900.  */

  int tm_wday; /* Day of week. [0-6] */

  int tm_yday; /* Days in year.[0-365] */

  int tm_isdst; /* DST. [-1/0/1]*/


#ifdef __USE_BSD

  long int tm_gmtoff; /* Seconds east of UTC.  */

  __const char *tm_zone; /* Timezone abbreviation.  */

#else

  long int __tm_gmtoff; /* Seconds east of UTC.  */

  __const char *__tm_zone; /* Timezone abbreviation.  */

#endif

};

strptime("1970-01-01 00:00:00","%Y-%m-%d %H:%M:%S",&tm); 이런 식으로 쓰인다.

mktime 은 struct tm 구조체를 통해 epoch time 을 구해내는 함수이다. 근데 이 함수는 epoch time 을 구할때 struct tm 의 날짜와 시간을 바로 사용하는 것이 아니라 현재 컴퓨터의 time zone에 따라 epoch time을 구한다.

예를 들어 strptime("1970-01-01 00:00:00","%Y-%m-%d %H:%M:%S",&tm) 를 통해 struct tm 구조체를 얻고 
mktime(&
tm) 을 통해 struct tm 구조체를 epoch time 으로 바꾸었다고 가정하자.

예상 epoch time 은 0 이어야 실제로는 -32400 값이 나온다. 이유는 현재 내 컴퓨터의 time zone 이 KST 즉 한국으로 되어있다.

한국은 UTC 시간보다 9시간 늦는다. 즉 UTC 시간이 1970-01-01 00:00:00 이라면 KST 시간은  1970-01-01 09:00:00 이다.

위의 mktime() 은 1970-01-01 00:00:00 이 시간을 한국시간이라 생각하고 -32400 epoch time 을 반환한 것이다.

내가 원하는 시간은 UTC 시간인데 전혀 다른 값이 나온것이다. 이럴때 time zone 을 바꾸는 방법이 있다.


Time zone 을 UTC로 바꾸는 방법 (mktime UTC ) 

 setenv("TZ", "UTC", 1);

 time=mktime(&tm);

/// setenv 를 통해 자신의 TIme Zone 을 바꾸어 사용하면 된다.
/// 1970-01-01 00:00:00 을 mktime 하였을때 우리가 원하던 0 epoch time 이 나온다.



또다른 방법으로 struct tm 의 tm_gmtoff 값을 이용하는 방법이다.

struct tm 의 tm_gmtoff 은 현재 Time Zone 에 대해 UTC와 차이를 말한다. Time zone 이 KST 즉 한국이면 tm_gmtoff는 32400 값을 나타낸다. 즉 UTC 보다 32400초 (9시간) 늦다는 것이다.


struct tm 의 tm_gmtoff 을 이용하여 mktime 의 반환값을 UTC 값으로 바꾸기

 struct tm tm;

 strptime("1970-01-01 00:00:00","%Y-%m-%d %H:%M:%S",&tm)
 time=mktime(&tm);

 printf("epoch time = %lli", time + tm.tm_gmtoff);


 결과는 0 이다.

1970-01-01 00:00:00 을 mktime 하였을때 mktime 은 이 시간을 KST 즉 한국 시간이라 생각하고 UTC epoch time 을 구하기 위해 -32400 초를 뺀 값을 반환한다. (1970-01-01 00:00:00 이 0 epoch time 이므로 -32400 으로 뺀 -32400 반환)

  time + tm.tm_gmtoff 은 위의 결과만 보자면 -32400 + 32400 이다. 즉 0 을 출력한다.




 정리

 mktime() 은 인자로 받은 struct tm 구조체의 시간을 Time Zone(컴퓨터의 지역시간)이라고 생각하고 이를 토대로 UTC epoch time 을 구한다.

다시 예를 들면 1970년 01월 01일 00시 00 분 00초 값을 갖는 struct tm 구조체값을 KST(한국 시간)이라고 생각하고 (한국 시간은 UTC 시간보다 9시간 늦다.) 9시간(32400초)을 뺀 값의 epoch time을 구한다. 


struct tm 의 tm_gmtoff 값은 struct tm 에 들어있는 값을 UTC 시간이라고 생각하고 현재 Time Zone 과의 시간차이를 나타낸다.

다시 예를 들면 KST(한국 시간)은 UTC 보다 9시간 늦으므로 32400 값을 갖는다.


글은 정말 못 썼는데.. 이 문제로 골머리 썩은 사람들은 무슨 말인지 이해 할 것이다...

반응형