1. 程式人生 > >C++程式設計中時間使用總結

C++程式設計中時間使用總結

各種時間類/資料結構

與時間相關的類和資料結構有

1. CTime

2. CTimeSpan

3. __time64_t和time_t

4. struct tm

5. SYSTEMTIME

6. FILETIME

7. DBTIMESTAMP

CTime

// 微軟文件

http://msdn.microsoft.com/zh-cn/library/78zb0ese.aspx

1.1 定義

class CTime
{
public:
	static CTime WINAPI GetCurrentTime() throw();
	static BOOL WINAPI IsValidFILETIME(_In_ const FILETIME& ft) throw();

	CTime() throw();
	CTime(_In_ __time64_t time) throw();
	CTime(_In_ int nYear, _In_ int nMonth, _In_ int nDay, _In_ int nHour, _In_ int nMin, _In_ int nSec, _In_ int nDST = -1);
	CTime(_In_ WORD wDosDate, _In_ WORD wDosTime, _In_ int nDST = -1); 
	CTime(_In_ const SYSTEMTIME& st, _In_ int nDST = -1);
	CTime(_In_ const FILETIME& ft, _In_ int nDST = -1);
	CTime(_In_ const DBTIMESTAMP& dbts, _In_ int nDST = -1) throw();

	CTime& operator=(_In_ __time64_t time) throw();

	CTime& operator+=(_In_ CTimeSpan span) throw();
	CTime& operator-=(_In_ CTimeSpan span) throw();

	CTimeSpan operator-(_In_ CTime time) const throw();
	CTime operator-(_In_ CTimeSpan span) const throw();
	CTime operator+(_In_ CTimeSpan span) const throw();

	bool operator==(_In_ CTime time) const throw();
	bool operator!=(_In_ CTime time) const throw();
	bool operator<(_In_ CTime time) const throw();
	bool operator>(_In_ CTime time) const throw();
	bool operator<=(_In_ CTime time) const throw();
	bool operator>=(_In_ CTime time) const throw();

	struct tm* GetGmtTm(_Out_ struct tm* ptm) const;
	struct tm* GetLocalTm(_Out_ struct tm* ptm) const;

	bool GetAsSystemTime(_Out_ SYSTEMTIME& st) const throw();
	bool GetAsDBTIMESTAMP(_Out_ DBTIMESTAMP& dbts) const throw();

	__time64_t GetTime() const throw();

	int GetYear() const throw();
	int GetMonth() const throw();
	int GetDay() const throw();
	int GetHour() const throw();
	int GetMinute() const throw();
	int GetSecond() const throw();
	int GetDayOfWeek() const throw();

	// formatting using "C" strftime
	CString Format(_In_z_ LPCTSTR pszFormat) const;
	CString FormatGmt(_In_z_ LPCTSTR pszFormat) const;
	CString Format(_In_ UINT nFormatID) const;
	CString FormatGmt(_In_ UINT nFormatID) const;

#if defined(_AFX) && defined(_UNICODE)
	// for compatibility with MFC 3.x
	CString Format(_In_z_ LPCSTR pFormat) const;
	CString FormatGmt(_In_z_ LPCSTR pFormat) const;
#endif

#ifdef _AFX
	CArchive& Serialize64(_In_ CArchive& ar);
#endif

private:
	__time64_t m_time;
};

1.2 使用

1.2.1 構造

// 199331922:15:00 (年月日時分秒)

CTime t(1999, 3, 19, 22, 15, 0);

nYear  19703000

nMonth 112

nDay 131

nHour 0-23

nMin 0-59

nSec 0-59

1.2.2 格式化成字串

CTime t(1999, 3, 19, 22, 15, 0); 

// "Friday, March 19, 1999"

CString s = t.Format(_T("%A, %B %d, %Y"));

CTime::Format的引數

%a    縮寫的星期名稱

%A    完整星期名稱

%b    縮寫的月份名稱

%B    完整的月份名稱。

%c    日期和時間表示恰當的區域設定

%d    日期為十進位制數字 (01 - 31) 的月份

%H    以 24 小時格式 (00 - 23) 的點

%I    以 12 小時格式 (01 - 12) 的點

%j    日期為十進位制數字 (001 - 366)

%m    為十進位制數字 (01 - 12) 的月份

%M    為十進位制數字 (00 - 59) 的分鐘

%p    12 小時時鐘的當前區域設定的 A.M/P.M. 指示器

%S    其次為十進位制數字 (00 - 59)

%U    周為十進位制數字的年份,週日為一週的第一天 

(00 - 53)

%w    周為十進位制數字 (0 - 6 是星期天)

%W    周為十進位制數字的年份,星期一為一週的第一天 (00 - 53)

%x    當前區域設定的日期顯示

%X    當前區域設定的時間顯示

%y    無世紀年,為十進位制數字 (00 - 99)

%Y    世紀年,為十進位制數字

%z, %Z    根據登錄檔設定,無論是時區名稱或時區縮寫,如果時區未知,則沒有字元

%%    百分號

1.2.3 獲取當前時間

CTime tm = CTime::GetCurrentTime();

__time64_t CTime::GetTime( ) const throw( ); //  返回1970年一月1日到CTime物件之間的秒數

1.2.4 獲取 年月日時分秒

// 10:15 PM March 19, 1999

CTime t(1999, 3, 19, 22, 15, 0);

ATLASSERT(t.GetYear() == 1999);

ATLASSERT(t.GetMonth() == 3);

ATLASSERT(t.GetDay() == 19);

ATLASSERT(t.GetHour() == 22);

ATLASSERT(t.GetMinute() == 15);

ATLASSERT(t.GetSecond() == 0);

ATLASSERT(t.GetDayOfWeek() == 1);

ATLASSERT(t.GetDayOfWeek() == 7);

1.2.5 CTime轉tm; CTimetime_t; CTimeSYSTEMTIME;

struct tm* CTime::GetGmtTm(struct tm* ptm) const;

struct tm* CTime::GetLocalTm(struct tm* ptm) const;

__time64_t CTime::GetTime( ) const throw( ); //  返回1970年一月1日到CTime物件之間的秒數

bool GetAsSystemTime(_Out_ SYSTEMTIME& st) const throw();

bool GetAsDBTIMESTAMP(_Out_ DBTIMESTAMP& dbts) const throw();

1.2.6 舉例

CTime time1 = CTime::GetCurrentTime(); // 獲取當前時間

CTime time2(1999, 3, 19, 22, 15, 0); // 構造一個時間

CTime time3(1999, 3, 18, 22, 14, 30); // 構造一個時間

// time2與time3 時間相差1天0小時0分鐘30秒(1 * 24 * 60 * 60 + 30)

CTimeSpan timeSpan = time2 - time3;

int nTemp = 0;

nTemp = timeSpan.GetDays(); // 1

nTemp = timeSpan.GetTotalHours(); // 24

nTemp = timeSpan.GetHours(); // 0

nTemp = timeSpan.GetTotalMinutes(); // 1440

nTemp = timeSpan.GetMinutes(); // 0

nTemp = timeSpan.GetTotalSeconds(); // 86430

nTemp = timeSpan.GetSeconds(); // 30

CString strTemp = time2.Format(_T("%Y-%m-%d %H:%M:%S %A")); // 輸出格式: 1999-03-19 22:15:00 Friday

nTemp = time2.GetYear(); // 1999

nTemp = time2.GetMonth(); // 3

nTemp = time2.GetDay(); // 19

nTemp = time2.GetHour(); // 22

nTemp = time2.GetMinute(); // 15

nTemp = time2.GetSecond(); // 0

nTemp = time2.GetDayOfWeek(); // 6

. CTimeSpan

用於表示時間範圍

2.1 定義

class CTimeSpan
{
public:
	CTimeSpan() throw();
	CTimeSpan(_In_ __time64_t time) throw();
	CTimeSpan(_In_ LONG lDays,	_In_ int nHours, _In_ int nMins, _In_ int nSecs) throw();

	LONGLONG GetDays() const throw();
	LONGLONG GetTotalHours() const throw();
	LONG GetHours() const throw();
	LONGLONG GetTotalMinutes() const throw();
	LONG GetMinutes() const throw();
	LONGLONG GetTotalSeconds() const throw();
	LONG GetSeconds() const throw();

	__time64_t GetTimeSpan() const throw();

	CTimeSpan operator+(_In_ CTimeSpan span) const throw();
	CTimeSpan operator-(_In_ CTimeSpan span) const throw();
	CTimeSpan& operator+=(_In_ CTimeSpan span) throw();
	CTimeSpan& operator-=(_In_ CTimeSpan span) throw();
	bool operator==(_In_ CTimeSpan span) const throw();
	bool operator!=(_In_ CTimeSpan span) const throw();
	bool operator<(_In_ CTimeSpan span) const throw();
	bool operator>(_In_ CTimeSpan span) const throw();
	bool operator<=(_In_ CTimeSpan span) const throw();
	bool operator>=(_In_ CTimeSpan span) const throw();
public:
	CString Format(_In_z_ LPCTSTR pszFormat) const;		
	CString Format(_In_ UINT nID) const;
#if defined(_AFX) && defined(_UNICODE)
	// for compatibility with MFC 3.x
	CString Format(_In_z_ LPCSTR pFormat) const;
#endif

#ifdef _AFX
	CArchive& Serialize64(_In_ CArchive& ar);
#endif

private:
	__time64_t m_timeSpan;
};

2.2 舉例

CTime time1 = CTime::GetCurrentTime(); // 獲取當前時間

CTime time2(1999, 3, 19, 22, 15, 0); // 構造一個時間

CTime time3(1999, 3, 18, 22, 14, 30); // 構造一個時間

// time2與time3 時間相差1天0小時0分鐘30秒(1 * 24 * 60 * 60 + 30)

CTimeSpan timeSpan = time2 - time3;

int nTemp = 0;

nTemp = timeSpan.GetDays(); // 1

nTemp = timeSpan.GetTotalHours(); // 24

nTemp = timeSpan.GetHours(); // 0

nTemp = timeSpan.GetTotalMinutes(); // 1440

nTemp = timeSpan.GetMinutes(); // 0

nTemp = timeSpan.GetTotalSeconds(); // 86430

nTemp = timeSpan.GetSeconds(); // 30

CString strTemp = time2.Format(_T("%Y-%m-%d %H:%M:%S %A")); // 輸出格式: 1999-03-19 22:15:00 Friday

nTemp = time2.GetYear(); // 1999

nTemp = time2.GetMonth(); // 3

nTemp = time2.GetDay(); // 19

nTemp = time2.GetHour(); // 22

nTemp = time2.GetMinute(); // 15

nTemp = time2.GetSecond(); // 0

nTemp = time2.GetDayOfWeek(); // 6

__time64_t和time_t

就是一個64位的整形可以表示秒數

typedef __time64_t time_t;      /* time value */

typedef __int64 __time64_t;     /* 64-bit time value */

time_t now;

time(&now); // 獲取當前時間

struct tm

struct tm {

        int tm_sec;     /* seconds after the minute - [0,59] */

        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_isdst為正。 */

                        /* 不實行夏令時的進候,tm_isdst為0;不瞭解情況時,tm_isdst()為負*/

};

4.1 CTimetm

CTime有函式可以填充tm;

struct tm* CTime::GetGmtTm(struct tm* ptm) const; // 獲取CTime物件的時間

struct tm* CTime::GetLocalTm(struct tm* ptm) const; // 獲取當前時間

4.2 CTimetm

CTime time2(1999, 3, 19, 22, 15, 0); // 構造一個時間

tm osTime1, osTime2;

time2.GetLocalTm(&osTime1);

time2.GetGmtTm(&osTime2);

ATLTRACE(_T("Difference between local time and GMT is %d hours.\n"), osTime1.tm_hour - osTime2.tm_hour);

 

4.3 time_ttm互轉

4.3.1 time_t轉tm

time_t tt = time2.GetTime();

struct tm tm1;

localtime_s(&tm1, &tt);

struct tm temptm = *localtime(&t1); // 這個函式也可以, 但是返回的是一個指標, 儘量不使用

4.3.2 tmtime_t

struct tm tm1;

......

time_t tt2 = mktime(&tm1);

SYSTEMTIME

5.1 定義

typedef struct _SYSTEMTIME {

    WORD wYear; // The current year.

    WORD wMonth; // The current month; January is 1.

    WORD wDayOfWeek; // The current day of the week; Sunday is 0, Monday is 1, and so on.

    WORD wDay; // The current day of the month.

    WORD wHour; // The current hour.

    WORD wMinute; // The current minute.

    WORD wSecond; // The current second.

    WORD wMilliseconds; // The current millisecond.

};

SYSTEMTIME是屬於Window上的結構

5.2 例子

SYSTEMTIME systime;GetSystemTime(&systime);

5.3 tmSYSTEMTIME 互轉

5.3.1 tmSYSTEMTIME

struct tm tm1;

......

SYSTEMTIME st = {1900 + tm1.tm_year, 1 + tm1.tm_mon, tm1.tm_wday, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec, 0};

5.3.2 SYSTEMTIMEtm

// 四年一閏, 百年不閏, 四百年再閏.
bool IsLeapYear(int nYear)
{
	// 閏年: 能被400整除的是閏年; 能被4整除並且不被100整除的也是閏年;
	return (0 == (nYear % 400)) || ((0 == (nYear % 4)) && (0 != (nYear % 100)));
}

int GetYearDay(int nYear, int nMonth, int nMDay)
{
	int nMonthDaysLeap[12]		= {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	int nMonthDaysNonLeap[12]	= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	int* pDays = 0;
	// 簡單校驗
	if(1 > nMonth || 12 < nMonth || 1 > nMDay)
	{
		return 0;
	}

	// 是否閏年
	pDays = IsLeapYear(nYear) ? nMonthDaysLeap : nMonthDaysNonLeap;
	if(nMDay > pDays[nMonth - 1])
	{
		return 0;
	}

	int nYearDay = nMDay;
	--nMonth;
	int i = 0;
	for(i = 0; i < nMonth; ++i)
	{
		nYearDay += pDays[i];
	}
	return nYearDay;
}

SYSTEMTIME st;
......
int nYearDay = GetYearDay(st.wYear, st.wMonth, st.wDay);
struct tm tm2 = {st.wSecond, st.wMinute, st.wHour, st.wDay, st.wMonth-1, st.wYear-1900, st.wDayOfWeek, nYearDay - 1, 0};

. FILETIME

typedef struct _FILETIME {

    DWORD dwLowDateTime;

    DWORD dwHighDateTime;

} FILETIME

6.1 相關函式

BOOL SystemTimeToFileTime(CONST SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime);

BOOL FileTimeToSystemTime(CONST FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime);

6.2 FILETIME和SYSTEMTIME互轉

BOOL SystemTimeToFileTime(CONST SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime);

BOOL FileTimeToSystemTime(CONST FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime); 

時間的格式化

8.1 CTime::Format

CTime t(1999, 3, 19, 22, 15, 0); 

// "Friday, March 19, 1999"

CString s = t.Format(_T("%A, %B %d, %Y"));

8.2 strftime

size_t strftime(char *strDest, size_t maxsize, const char *format, const struct tm *timeptr);

%a 星期幾的簡寫 

%A 星期幾的全稱 

%b 月分的簡寫 

%B 月份的全稱 

%c 標準的日期的時間串 

%C 年份的後兩位數字 

%d 十進位制表示的每月的第幾天 

%D 月/天/年 

%e 在兩字元域中,十進位制表示的每月的第幾天 

%F 年-月-日 

%g 年份的後兩位數字,使用基於周的年 

%G 年分,使用基於周的年 

%h 簡寫的月份名 

%H 24小時制的小時 

%I 12小時制的小時

%j 十進位制表示的每年的第幾天 

%m 十進位制表示的月份 

%M 十時製表示的分鐘數 

%n 新行符 

%p 本地的AM或PM的等價顯示 

%r 12小時的時間 

%R 顯示小時和分鐘:hh:mm 

%S 十進位制的秒數 

%t 水平製表符 

%T 顯示時分秒:hh:mm:ss 

%u 每週的第幾天,星期一為第一天 (值從0到6,星期一為0)

%U 第年的第幾周,把星期日做為第一天(值從0到53)

%V 每年的第幾周,使用基於周的年 

%w 十進位制表示的星期幾(值從0到6,星期天為0)

%W 每年的第幾周,把星期一做為第一天(值從0到53) 

%x 標準的日期串 

%X 標準的時間串 

%y 不帶世紀的十進位制年份(值從0到99)

%Y 帶世紀部分的十制年份 

%z,%Z 時區名稱,如果不能得到時區名稱則返回空字元。

%% 百分號

小結

1. 在上面的結果中, SYSTEMTIME結構可以提高毫秒資訊.

2. CTime, struct tm, time_t, SYSTEMTIME之間都可以直接或者間接的互轉.