C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

컴포넌트/라이브러리
Delphi/C++Builder Programming Components&Libraries
[421] time_t 를 완전히 대체하는 CTime 클래스.
김태선 [jsdkts] 17085 읽음    2005-11-21 14:26
time_t 데이타형은 C 시절부터 전통적으로 사용해오던 날짜 시간형입니다.
시간을 1초단위로 다루는 long 형 4바이트 값으로, 여러군데 유용하게 사용할수 있는 자료형입니다.
이미 빌더에는 TDateTime 이라는 8바이트 실수를 기본으로 하는 우수한 날짜 시간 클래스가 있지만,
필요에 따라 1초단위로 다루는 4바이트 날짜 시간형을 사용하고 싶을때가 있습니다.
4바이트 날짜 시간형은 비록 정밀도가  2038년 1월까지지만
실무에 사용하기는 무리가 없는 날짜시간 형입니다. 소프트웨어 수명이 30년을 넘지는 않을 것이고
혹 넘는다 해도 30년 뒤에 수정해도 되므로.. --; (SW 수명이 10년이면 그것도 길다고 생각드는데...)

어쨌거나 4바이트의 전통적인 time_t 를 심심잖게 이용하는데 어디에도 이를 클래스화 해 놓은 것을
발견할 수 없어서, 잠시 시간을 내서 만들어 봤습니다.
time_t 를 쓰실 곳에 간편하게 CTime 으로 대체해서 넣을 수 있습니다.
충분히 모든 기능을 다 테스트한 것은 아니지만 제 프로그램에서 사용하기에 아무런 문제가 없는 수준이라
혹 필요하신 분이 있으면 쓰시라고 이렇게 공개합니다.
가상함수가 없으므로 ZeroMemory 로 초기화 하는 곳에 놓여도 문제가 없습니다.

VCL 종속적이 아니며, 아무 C++ 컴파일러에서도 사용할 수 있다는 장점이 있습니다.
아래 소스를 보시면 간편하게 이해되리라고 생각되어 자세한 사용법 설명은 생략합니다.

연산자 오버로딩 쪽은 완벽한 테스트를 일일이 한 것은 아니므로 혹 이상있으면 연락 바랍니다.
ATL의 CTime은 8바이트 날짜 시간형으로 명칭만 같을 뿐 기능은 다르므로 ATL CTime 을 쓰시는 분은
클래스명을 바꿔서 사용하세요.
소스는 별도 첨부했습니다.

그럼....

헤더

//---------------------------------------------------------------------------

#ifndef CTimeH
#define CTimeH

#include <time.h>
//---------------------------------------------------------------------------
// time_t 를 다루는 클래스
//        크기 4바이트 기존 time_t를 완전하게 대체하는 클래스.
//        주의 : time_t의 날짜 한계가 2038년 1월까지임. (2038년 직전 반드시 SW를 업글해야 함)
//        time_t는 long형으로 1970-1-1 0시 부터의 경과 시간을 초단위로 나타냄.
//        그러므로 초단위로 더하고 빼는 연산을 적용할 수 있음.
//
//
//     개선하시는 분은 아래에 작업하신 날짜와 성함을 기재해서 공개 바람.
//     Written by
//     날짜        개발자    코멘트
//     2005.11.      김태성     첫버전. 버그는 jsdkts@korea.com 으로 알려주심 감사하겠습니다.
//

class CTime            // ATL의 CTime과 명칭이 겹치니 그건 각자 알아서 하세요.
{
private:
    time_t        mTime;

public:
    static CTime GetCurrentTime()
    {
        return time(NULL);
    }
    CTime()
    {
        mTime = 0;
    }
    CTime( CTime& src )
    {
        mTime = src.mTime;
    }
    CTime( time_t atime )       // NULL을 대입하면 현재시간을 바로 세팅할수 있다.
    {
        if (atime == NULL)
            mTime = time(NULL);
        else
            mTime = atime;
    }
    CTime(int nYear, int nMonth, int nDay, int nHour=0, int nMin=0, int nSec=0, int nDST=-1)
    {
        Set(nYear, nMonth, nDay, nHour, nMin, nSec);
    }
    CTime    Set(int nYear, int nMonth, int nDay, int nHour=0, int nMin=0, int nSec=0, int nDST=-1)
    {
        if (nYear >= 2038)
            nYear = 2037;        // 날짜가 초과하면 mTime==-1만 세팅되므로 그것을 방지한다.
        else if (nYear < 1970)    // mktime 날짜가 1970년1월1일부터만 다루므로.
            nYear = 1970;
        struct tm  t;
        t.tm_sec    = nSec;
        t.tm_min    = nMin;
        t.tm_hour   = nHour;
        t.tm_mday   = nDay;
        t.tm_mon    = nMonth ? nMonth - 1 : 0;
        t.tm_year   = nYear % 1900;
        t.tm_isdst     = nDST;
        mTime = mktime(&t);
        // t.tm_wday                    //* Day of the week 자동 셋팅 됨.
        return *this;                    // 에러인 경우 -1 이 되돌려짐.
    }
    void    SetCurrentTime()
    {
        mTime = time(NULL);
    }

    // time_t time; 변수는 그냥 CTime  t = time; 식으로 바로 대입가능.
    // time_t 형에 역대입은 time_t time = t.time_t(); 로 됨.
    CTime& operator=( CTime& time )
    {
        mTime = time.mTime;
        return *this;
    }
    CTime& operator=( CTime time )
    {
        mTime = time.mTime;
        return *this;
    }
    CTime& operator+=( CTime& time )
    {
        mTime += time.mTime;
        return *this;
    }
    CTime& operator-=( CTime& time )
    {
        mTime -= time.mTime;
        return *this;
    }

    CTime operator-( CTime& time )
    {
        return mTime - time.mTime;
    }
    CTime operator+( CTime& time )
    {
        return mTime + time.mTime;
    }

    CTime& operator ++()
    {
        ++mTime;
        return *this;
    }
    CTime operator ++(int)
    {
        return mTime++;
    }
    CTime& operator --()
    {
        --mTime;
        return *this;
    }
    CTime operator --(int)
    {
        return mTime--;
    }

    bool operator==( CTime& time )
    {
        return mTime == time.mTime;
    }
    bool operator==( int time )
    {
        return mTime == time;
    }
    bool operator!=( CTime& time )
    {
        return mTime != time.mTime;
    }
    bool operator<( CTime& time )
    {
        return mTime < time.mTime;
    }
    bool operator>( CTime& time )
    {
        return mTime > time.mTime;
    }
    bool operator<=( CTime& time )
    {
        return mTime <= time.mTime;
    }
    bool operator>=( CTime& time )
    {
        return mTime >= time.mTime;
    }
    // 아래 몇줄은 차후 구현 또는 필요한 사람이 구현.
    //CTime(WORD wDosDate, WORD wDosTime, int nDST = -1);
    //CTime(const SYSTEMTIME& st, int nDST = -1);
    //CTime(const FILETIME& ft, int nDST = -1);
    //struct tm* GetGmtTm( struct tm* ptm = NULL );
    //struct tm* GetLocalTm( struct tm* ptm = NULL );
    //bool GetAsSystemTime( SYSTEMTIME& st );
    //bool GetAsDBTIMESTAMP( DBTIMESTAMP& dbts );

    time_t     time_t()
    {
        return mTime;
    }

    // GetYear GetMonth .. 등으로 안한 이유는.. Get을 안넣어도 날짜 시간은 그냥 의미가 와 닿으므로.
    int Year()
    {
        struct tm  *tt = localtime(&mTime);
        return tt->tm_year + 1900;
    }
    int Month()
    {
        struct tm  *tt = localtime(&mTime);
        return tt->tm_mon + 1;
    }
    int Day()
    {
        struct tm  *tt = localtime(&mTime);
        return tt->tm_mday;
    }
    int Hour()
    {
        struct tm  *tt = localtime(&mTime);
        return tt->tm_hour;
    }
    int Minute()
    {
        struct tm  *tt = localtime(&mTime);
        return tt->tm_min;
    }
    int Second()
    {
        struct tm  *tt = localtime(&mTime);
        return tt->tm_sec;
    }
    void     GetDate(int &year, int &month, int &day)
    {
        struct tm  *tt = localtime(&mTime);
        year     = tt->tm_year + 1900;
        month     = tt->tm_mon + 1;
        day     = tt->tm_mday;
    }
    void     GetTime(int &hour, int &min, int &sec)
    {
        struct tm  *tt = localtime(&mTime);
        hour    = tt->tm_hour;
        min     = tt->tm_min;
        sec     = tt->tm_sec;
    }

    int  GetDayOfWeek()
    {
        struct tm  *tt = localtime(&mTime);
        return tt->tm_wday;
    }

    static char buf[];

    char  *asctime()
    {
        struct tm  *tt = localtime(&mTime);
        return ::asctime(tt);    // 표준 asCTime은 끝에 \n 이 붙는다. 그리고 날짜 형식이 우리와 맞지 않다.
    }

    enum
    {
        NO_SEC             = 0x1,    // 초생략
        SHORT_YEAR        = 0x2,    // 년2자리로
        NO_SEPARATE        = 0x4,    // - : 같은 분할문자를 없앤다. sDateTime에서는 빈칸도 없앤다.
    };
    char  *sDateTime(int type = 0)
    {
        struct tm  *tt = localtime(&mTime);
        char  *fmt = "%04d-%02d-%02d %02d:%02d:%02d";
        if (type & NO_SEC)             // 초 생략하라.
            fmt = "%04d-%02d-%02d %02d:%02d";
        if (type & SHORT_YEAR)
            fmt[2] = '2';        // %02d 년도를 2자리로.
        sprintf(buf, fmt,
            type & SHORT_YEAR ? tt->tm_year % 100: tt->tm_year + 1900, tt->tm_mon + 1, tt->tm_mday,
            tt->tm_hour, tt->tm_min, tt->tm_sec);
        if (type & NO_SEPARATE)
            DeleteSeparate(buf);
        return buf;
    }
    char  *sDate(int type = 0)
    {
        struct tm  *tt = localtime(&mTime);
        char  *fmt = "%04d-%02d-%02d";
        if (type & SHORT_YEAR)
            fmt[2] = '2';        // %02d 년도를 2자리로.
        sprintf(buf, fmt,
            type & SHORT_YEAR ? tt->tm_year % 100: tt->tm_year + 1900, tt->tm_mon + 1, tt->tm_mday);
        if (type & NO_SEPARATE)
            DeleteSeparate(buf);
        return buf;
    }
    char  *sTime(int type = 0)
    {
        struct tm  *tt = localtime(&mTime);
        char  *fmt = "%02d:%02d:%02d";
        if (type & NO_SEC)
            fmt = "%02d:%02d";
        sprintf(buf, fmt, tt->tm_hour, tt->tm_min, tt->tm_sec);
        if (type & NO_SEPARATE)
            DeleteSeparate(buf);
        return buf;
    }
    // strftime 등에서 바로 사용하기 위해, 예)strftime(buf, 100, "%y%m%d %H%M%S", time.tm());
    struct tm  *tm()
    {
        return localtime(&mTime);
    }
    // strftime 에 준하는 포멧을 사용해야 한다.
    // 예:String datetime = t.Format("%Y.%m.%d %H:%M:%S");
    char  *Format(char *fmt)
    {
        strftime(buf, 100, fmt, tm());
        return buf;
    }

private:
    void    DeleteSeparate(char buf[])
    {
        char  *p = buf;
        for(int c = 0; buf[c]; c++)
        {
            if (buf[c] == '-' || buf[c] == ':' || buf[c] == ' ')
                continue;
            *p++ = buf[c];
        }
        *p = 0;
    }

};
//---------------------------------------------------------------------------

#endif


cpp 파일


#include <stdio.h>
#pragma hdrstop
#include <time.h>

#include "CTime.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)

//---------------------------------------------------------------------------

char CTime::buf[101];



예제
현재 시간 캡션에 표시하기.

CTime  t(NULL);
Caption = t.sDateTime();
// 또는
Caption = t.Format("%Y.%m.%d %H:%M:%S");

끝.
김태선 [jsdkts]   2005-12-20 19:35 X
정수에 대한 시간 연산을 형변환 없이 하려면
아래 연산자 오버로딩을 추가해야 합니다.

    CTime operator-(int time)
    {
        return mTime - time;
    }
    CTime operator+(int time)
    {
        return mTime + time;
    }

쓰다 보니 이게 필요해서 추가합니다.

+ -

관련 글 리스트
421 time_t 를 완전히 대체하는 CTime 클래스. 김태선 17085 2005/11/21
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.