시간 다룰 때는 주의하자

  • Post author:
  • Post category:
  • Post comments:3 Comments
  • Post last modified:December 21, 2007

WIN32에 있는 FILETIME로 표시된 값을 데이터베이스에 저장하는 코드가 있었다. 시간 값을 저장하기 위해 데이터베이스에서는 numeric 타입을 사용했다. FILETIME이 DWORD 두 개로 구성된 구조체이기 때문에 적당한 기본 타입이 없었기 때문이다.

어쨌거나 numeric 타입으로 시간 값을 저장하면 큰 문제가 있다. numeric 타입을 쓰게 되면, 이 값을 다시 데이터베이스의 기본 타입인 datetime으로 변환해야 시간 연산이 가능하다. Windows 프로그래머가 편하자고 이런 만행을 저지를 수는 없는 일이라 결국 이틀에 걸쳐 모든 코드를 손봤다. 하루는 기존 코드를 제대로 이해 못한 상태로 작업에 착수하여 결국 고친 코드를 모두 원래대로 돌려놓고 말았고, 어제 하루를 통째로 써서 일을 마쳤다. 이제와 생각해보면 반나절이면 끝났을 일인데, 반나절이 더 걸린 것이다. 문제의 원인은 시간이었다.

FILETIME은 1601년 1월 1일(UTC, 그리니치)을 기준으로 삼는다. 그리고 SQL Server 2005의 datetime은 1753년 1월 1일을, smalldatetime은 1900년 1월 1일을 기준으로 삼는다. 한데 기존 코드가 시간을 나타내는 별도의 클래스를 사용하지 않고 64비트 정수형을 썼기 때문에 문제가 발생했다.

__int64 time = 0;

이런 코드는 1601년 1월 1일을 나타내기 때문에 이 값을 datetime으로 변환해서 넣으려니 당연히 오류가 날 수밖에 없었다. 왜 자꾸 음수값이 나오나 했더니만 이 때문이었다.

참고. 때로는 1753년과 1601년 사이를 100 나노초로 계산했을 때 어느 정도의 시간이 되는지 알고 싶다면 이렇게 하면 된다.

SYSTEMTIME firstTime = {1601, 1, 0, 1, 0, 0, 0 , 0};
__int64 firstIntTime;
SystemTimeToFileTime(&firstTime, (LPFILETIME)&firstIntTime);

SYSTEMTIME secondTime = {1753, 1, 0, 1, 0, 0, 0 , 0};
__int64 secondIntTime;
SystemTimeToFileTime(&secondTime, (LPFILETIME)&secondIntTime);

__int64 substract = secondIntTime - firstIntTime
std::cout << substract << std::endl;
Author Details
Kubernetes, DevSecOps, AWS, 클라우드 보안, 클라우드 비용관리, SaaS 의 활용과 내재화 등 소프트웨어 개발 전반에 도움이 필요하다면 도움을 요청하세요. 지인이라면 가볍게 도와드리겠습니다. 전문적인 도움이 필요하다면 저의 현업에 방해가 되지 않는 선에서 협의가능합니다.
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
홍가이버
16 years ago

아…그렇군요…
유닉스 타임을 엑셀로 변환할때도 이런 셈(?)한적이 있는데…글 잘 읽고 트랙백 쏘아봅니다.

홍가이버
16 years ago

트랙백을 쏘려고 했으나…링크가 없어서 무산(?) ^^a

최재훈
16 years ago

한동안 트랙백 공격이 심해서 막아버렸습니다. 좀 불편하지만 직접 링크를 걸어서 트랙백 흉내를 내도 되니 굳이 있어야 한다는 생각이 들지 않았습니다.