반응형

http://blog.naver.com/elastica/50045305787




윈도우즈 프로그램을 개발하다 보면 날짜 및 시간 관련 처리가 필요한 경우가 많습니다.

특정 날짜 기준으로 어느 시간이 경과한 이후에 로그 파일을 지운다거나

특정 날짜에 프로그램을 실행 시킨다거나 또는 두 시간 사이의 차이점을 알아보고자 할때도

있구요..  다양한 요구 사항이 나올 수 있습니다.

 

위와 같은 요구사항에 적용될 수 있는 시간 및 날짜 관련 Tip 에 대해 정리해 보았습니다. 

1> 현재 시간 알아오기

 

아래의 두가지 코드 예제를 보시기 바랍니다.

 

첫번째 CTime::GetCurrentTime() 이 현재의 정확한 시간을 가지고 오는 함수 입니다.

CTime now1 = CTime::GetCurrentTime(); (O)

 

아래에 사용된 GetCurrentTime API 는 GetTickCount 로 대체 되었으며

시스템이 시작된 이후 경과돤 시간을 밀리세컨드로 리턴해 주는 함수입니다.

CTime now2  = GetCurrentTime(); (X)

 

CString 의 Format 을 통해 좀더 자세히 알아보겠습니다.

지금 시간이 3월 4일 오후 16:23 분 경입니다.

 

CTime::GetCurrentTime 을 사용했을 경우 정확한 현재 시간을 가져옴을 볼 수 있습니다.

 

 

*예제코드

CTime now1 = CTime::GetCurrentTime();

CTime now2  = GetCurrentTime();

 
 CString strTime1;
 
 strTime1.Format(_T("%04d-%02d-%02d %02d:%02d:%02d"),now1.GetYear(), now1.GetMonth(),now1.GetDay(),now1.GetHour(), now1.GetMinute(),now1.GetSecond());

 

 CString strTime2;

 strTime2.Format(_T("%04d-%02d-%02d %02d:%02d:%02d"),now2.GetYear(), now2.GetMonth(),now2.GetDay(),now2.GetHour(), now2.GetMinute(),now2.GetSecond());


 

2> 현재 시간 기준으로  특정 기간 전후 시간 알아오기

 

CTimeSpan  이란 클래스가 있습니다.

CTimeSpan( ) throw( );
CTimeSpan(
   __time64_t time 
) throw( );
CTimeSpan(
   LONG lDays,
   int nHours,
   int nMins,
   int nSecs 
) throw( );

 

CTimeSpan span(1,0,0,0); // 하루의 시간 간격을 의미합니다.

CTimeSpan span(0,1,0,0); // 한시간의 시간 간격을 의미합니다.

CTimeSpan span(0,0,1,0); // 1분의 시간 간격을 의미합니다.

CTimeSpan span(0,0,0,1); // 1초의 시간 간격을 의미합니다.

 

현재 시간 기준으로 하루 이후의 시간을 알고 싶은 경우 아래와 같이 코드를 작성합니다.

 

CTime now1 = CTime::GetCurrentTime();

 CTimeSpan span(1,0,0,0);

 CTime tomorrow = now1 + span;

 
 CString strTime1;
  
 strTime1.Format(_T("%04d-%02d-%02d %02d:%02d:%02d"),tomorrow.GetYear(), tomorrow.GetMonth(),tomorrow.GetDay(),
  tomorrow.GetHour(), tomorrow.GetMinute(),tomorrow.GetSecond() );

 

현재 시간은 4월 3일 16:33 분 경입니다. 정확하게 하루 이후의 날짜와 시간을 가지고 오는 것을

확인 하실 수 있습니다.

 

만약 하루 이전의 시간을 가지고 오고 싶으면 CTime tomorrow = now1  - span; 로 수정하시면 되겠죠.

 

시간 계산에 있어  범하기 쉬운 오류가 있습니다.

아래의 코드를 보시기 바랍니다.

 

CTime curTime = CTime::GetCurrentTime();
 // 스케쥴 실행시간
 CTime schTime(curTime.GetYear(), curTime.GetMonth(), curTime.GetDay() + 1, 0, 0, 0);
 CTimeSpan resultTime = schTime - curTime;

언뜻보면 문제가 없어 보이지만 curTime.GetDay() + 1 에서 에러가  발생한 가능성이 있습니다.

 

CTime 클래스의 생성자는 다음과 같습니다.

 

CTime(
   int nYear,
   int nMonth,
   int nDay,
   int nHour,
   int nMin,
   int nSec,
      int nDST = -1 
);

즉 세번째 인자는 Day 로써 최고 31까지 값이 있습니다.

 

그런데 만약 31일에 위의 코드를 실행하면 curTime.GetDay() + 1  = 32 가 되므로 예외가 발생하게

됩니다.

 

3>두 시간의 간격을 알아오는 방법

 아쉽게도 CTime 클래스는 최소 단위가 초(Second) 까지 입니다.

따라서 좀더 정밀한 시간 비교를 위해서는 적합하지가 않습니다.

 

초단위까지 동일하더라도 실제 두시간 사이에는 밀리 세컨드 단위로 차이가 나게 되어 있습니다.

이런 경우 각 시간의 간격(Gap) 을 가져오는 방법입니다.

 

FILETIME 이란 구조체가 있습니다.

 

정의는 아래와 같습니다.

typedef struct _FILETIME {
   DWORD dwLowDateTime;   /* low 32 bits  */
   DWORD dwHighDateTime;  /* high 32 bits */
} FILETIME, *PFILETIME, *LPFILETIME;

 

상위 32 비트  하위 32비트 즉 64비트 수준까지 데이터를 담을수 있는 구조입니다.

 

SYSTEMTIME 으로 설정된 시간을 FILETIME 으로 변경하는 API 로 SystemTimeToFileTime 라는 것이 있습니다.

SystemTime 을 FileTime 으로 변경시키는 함수 입니다.

 

BOOL WINAPI SystemTimeToFileTime(
  __in   const SYSTEMTIME *lpSystemTime,
  __out  LPFILETIME lpFileTime
);

아래 예제를 보시기 바랍니다.

 

 

시작 시간과 종료 시간이 절대적으로 동일하지만 않다면 두 시간 사이의 간격을

밀리 세컨드(ullDif ) 단위와 초(TimeInterval) 단위로 알아 볼수가 있습니다.

 

 SYSTEMTIME StartTime,EndTime;
  
 GetLocalTime(&StartTime);;//시작 시간

 Sleep(1000);

/* 두시간이 밀리세컨드 단위까지 동일하지 않아야 함 */

 GetLocalTime(&EndTime);;//종료시간
 
 FILETIME fTm1, fTm2;

 ULONGLONG *ullVal1, *ullVal2;
 ULONGLONG ullDif;
 float TimeInterval;
 SystemTimeToFileTime(&StartTime, &fTm1);
 SystemTimeToFileTime(&EndTime, &fTm2);

 
 ullVal1 = (ULONGLONG *)&fTm1;
 ullVal2 = (ULONGLONG *)&fTm2;

 ullDif = *ullVal2 - *ullVal1;  //100 나노 세컨드 단위

 TimeInterval = float(ullDif /10000) /1000; //다운받은 간격 초단위로 

 

4>특정 시간 이후 타이머 설정하는 방법

현재 시간 기준으로 특정 시점에 특정 작업을 실행할 필요성이

있는 경우가 있습니다.

예약 시스템이나 알람 시스템에서 사용이 될거 같네요.

두가지 예제 입니다.

 

*현재 시간 기준으로 얼마 이후에 실행하는 방법

 

CTime now = CTime::GetCurrentTime(); //현재시간
 CTime startTime;

 //오늘 기준 시작 시간에서 1일 1시간 1분 1초 후에 타이머를 실행하고 싶은 경우
 CTimeSpan sp(1,1,1,1);  
  
 startTime  = now + sp;
 CTimeSpan GapTime = startTime - now;
 
 int intTotalSeconds1 = (int)GapTime.GetTotalSeconds();

 //타이머는 밀리세컨드 단위이므로 1000을 곱해야 함
 SetTimer(0,intTotalSeconds1*1000,NULL);  

*특정 날짜에 실행하고 싶은 경우 

 

 //특정날짜에 실행하고 싶은 경우 아래 코드는 4월 10일 0:0:0 기준
 CTime startTime1(now.GetYear(), now.GetMonth(), 10, 0,0,0);

 GapTime = startTime1 - now;

 

 int intTotalSeconds2 = (int)GapTime.GetTotalSeconds();

 //타이머는 밀리세컨드 단위이므로 1000을 곱해야 함
 SetTimer(1,intTotalSeconds2*1000,NULL);  

 

반응형

+ Recent posts