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 構造
// 1993年3月19日22:15:00 (年月日, 時分秒)
CTime t(1999, 3, 19, 22, 15, 0);
nYear 1970–3000
nMonth 1–12
nDay 1–31
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 周為十進位制數字的年份,週日為一週的第一天
%w 周為十進位制數字 (0 - 6 ;0 是星期天)
%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; CTime轉time_t; CTime轉SYSTEMTIME;
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 CTime與tm
CTime有函式可以填充tm;
struct tm* CTime::GetGmtTm(struct tm* ptm) const; // 獲取CTime物件的時間
struct tm* CTime::GetLocalTm(struct tm* ptm) const; // 獲取當前時間
4.2 CTime轉tm
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_t與tm互轉
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 tm轉time_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 tm與SYSTEMTIME 互轉
5.3.1 tm轉SYSTEMTIME
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 SYSTEMTIME轉tm
// 四年一閏, 百年不閏, 四百年再閏.
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之間都可以直接或者間接的互轉.