|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionAside from strings, another area where things are probably a little more messy in the C++ and Windows world than it needed to be, has to be the date and time area. Starting with C and with every library added, there are so many ways to get the date and time that people can easily get confused. So in this article I hope to summarize and somewhat simplify the various date and time functionalities in Windows C++. Some terminologyAs always, there are a few jargons that you may have to know about, before getting into this concept, so I thought I should list them right at the beginning: UTC (Coordinated Universal Time) : This is the standard international time or the Greenwich Mean Time. epoch : number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time. 1. ASNI Standard LibraryOur first stop is the ANSI Standard library and the time.h header file. As its names indicates, the roots originate in C, so everything is designed in a very C-ish form (i.e. structures, etc...) I like to think of the contents of this file in two portions:
This article will only deal with calendar times.
The calendar time information in the Standard Library header file can themselves be broken into at leasttwo groups:
According to MSDN, in all versions of Microsoft C/C++ except Microsoft C/C++ version 7.0, and in
all versions of Microsoft Visual C++, the 2. Microsoft implementationsOver years Microsoft has added its own version of date and time functions which this article will now try to cover. We will begin our journey first with the Win32 API functions and then with the MFC functions available. 2.1 Win32 APIWith the Win32 API, Microsoft did not provide any direct functions to calculate time differences or provide capability to compare time values other than file times. Instead, it provided three basic structures, two of which will be talked about here and some 20 basic functions to retrieve various time information and convert between various time formats. At the heart of the Win32 date and time functionalities, are the the typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; } FILETIME, *PFILETIME, *LPFILETIME; // // System time is represented with the following structure: // typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; As you can tell, the As for the other structure, Microsoft decided to
define the 2.1.1 Getting System TimeWell, this is the easiest part. You can use the 2.1.2 Obtaining relative timesThis is where things get a big trickier. This is essentially what you need to do:
a) Convert your times from SYSTEMTIME st;
FILETIME ft;
LARGE_INTEGER li;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
Note : Sometimes some avid programmers try to take a shortcut and
directly use a The LARGE_INTEGER structure is defined as following: typedef union _LARGE_INTEGER { struct { DWORD LowPart; LONG HighPart; }; LONGLONG QuadPart; } LARGE_INTEGER; Although both of these have the same binary format, the address of all 2.1.3 Other useful functionsIn the Win32 date and time world, probably one of the more useful functions that you will run into
is the If you are building a treeview showing the file system, you may find the As for the rest of the functions available, here is a list of them from MSDN:
2.2 MFC datetime classesThe MFC framework simplified working with times considerably by introducing two wrapper classes,
the 2.2.1 CTime:A Microsoft provides 7 different constructors for the
By incorporating the ANSI In addition this class also overloads the +, -, = , ==, <, <<, >> operators to provide many more useful features. You can find the definition of class CTime { public: // Constructors static CTime PASCAL GetCurrentTime(); CTime(); CTime(time_t time); CTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, int nDST = -1); CTime(WORD wDosDate, WORD wDosTime, int nDST = -1); CTime(const CTime& timeSrc); CTime(const SYSTEMTIME& sysTime, int nDST = -1); CTime(const FILETIME& fileTime, int nDST = -1); const CTime& operator=(const CTime& timeSrc); const CTime& operator=(time_t t); // Attributes struct tm* GetGmtTm(struct tm* ptm = NULL) const; struct tm* GetLocalTm(struct tm* ptm = NULL) const; BOOL GetAsSystemTime(SYSTEMTIME& timeDest) const; time_t GetTime() const; int GetYear() const; int GetMonth() const; // month of year (1 = Jan) int GetDay() const; // day of month int GetHour() const; int GetMinute() const; int GetSecond() const; int GetDayOfWeek() const; // 1=Sun, 2=Mon, ..., 7=Sat // Operations // time math CTimeSpan operator-(CTime time) const; CTime operator-(CTimeSpan timeSpan) const; CTime operator+(CTimeSpan timeSpan) const; const CTime& operator+=(CTimeSpan timeSpan); const CTime& operator-=(CTimeSpan timeSpan); BOOL operator==(CTime time) const; BOOL operator!=(CTime time) const; BOOL operator<(CTime time) const; BOOL operator>(CTime time) const; BOOL operator<=(CTime time) const; BOOL operator>=(CTime time) const; // formatting using "C" strftime CString Format(LPCTSTR pFormat) const; CString FormatGmt(LPCTSTR pFormat) const; CString Format(UINT nFormatID) const; CString FormatGmt(UINT nFormatID) const; #ifdef _UNICODE // for compatibility with MFC 3.x CString Format(LPCSTR pFormat) const; CString FormatGmt(LPCSTR pFormat) const; #endif // serialization #ifdef _DEBUG friend CDumpContext& AFXAPI operator<<(CDumpContext& dc, CTime time); #endif friend CArchive& AFXAPI operator<<(CArchive& ar, CTime time); friend CArchive& AFXAPI operator>>(CArchive& ar, CTime& rtime); private: time_t m_time; }; 2.2.2 CTimeSpanThe class CTimeSpan { public: // Constructors CTimeSpan(); CTimeSpan(time_t time); CTimeSpan(LONG lDays, int nHours, int nMins, int nSecs); CTimeSpan(const CTimeSpan& timeSpanSrc); const CTimeSpan& operator=(const CTimeSpan& timeSpanSrc); // Attributes // extract parts LONG GetDays() const; // total # of days LONG GetTotalHours() const; int GetHours() const; LONG GetTotalMinutes() const; int GetMinutes() const; LONG GetTotalSeconds() const; int GetSeconds() const; // Operations // time math CTimeSpan operator-(CTimeSpan timeSpan) const; CTimeSpan operator+(CTimeSpan timeSpan) const; const CTimeSpan& operator+=(CTimeSpan timeSpan); const CTimeSpan& operator-=(CTimeSpan timeSpan); BOOL operator==(CTimeSpan timeSpan) const; BOOL operator!=(CTimeSpan timeSpan) const; BOOL operator<(CTimeSpan timeSpan) const; BOOL operator>(CTimeSpan timeSpan) const; BOOL operator<=(CTimeSpan timeSpan) const; BOOL operator>=(CTimeSpan timeSpan) const; #ifdef _UNICODE // for compatibility with MFC 3.x CString Format(LPCSTR pFormat) const; #endif CString Format(LPCTSTR pFormat) const; CString Format(UINT nID) const; // serialization #ifdef _DEBUG friend CDumpContext& AFXAPI operator<<(CDumpContext& dc,CTimeSpan timeSpan); #endif friend CArchive& AFXAPI operator<<(CArchive& ar, CTimeSpan timeSpan); friend CArchive& AFXAPI operator>>(CArchive& ar, CTimeSpan& rtimeSpan); private: time_t m_timeSpan; friend class CTime; }; 2.2.3 COleDateTimeThe other major date time class incorporated into MFC is the Now in the world of COM and Automation, Microsoft decided to define a big union of
many different types known as the The If you look at the list of constructors for COleDateTime( const VARIANT& varSrc );
COleDateTime( DATE dtSrc );
These two differences are indeed the reason for its existence. As of version 4.0 of MFC, the database programming functions of MFC use
///////////////////////////////////////////////////////////////////////////// // COleDateTime class class COleDateTime { // Constructors public: static COleDateTime PASCAL GetCurrentTime(); COleDateTime(); COleDateTime(const COleDateTime& dateSrc); COleDateTime(const VARIANT& varSrc); COleDateTime(DATE dtSrc); COleDateTime(time_t timeSrc); COleDateTime(const SYSTEMTIME& systimeSrc); COleDateTime(const FILETIME& filetimeSrc); COleDateTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec); COleDateTime(WORD wDosDate, WORD wDosTime); // Attributes public: enum DateTimeStatus { valid = 0, invalid = 1, // Invalid date (out of range, etc.) null = 2, // Literally has no value }; DATE m_dt; DateTimeStatus m_status; void SetStatus(DateTimeStatus status); DateTimeStatus GetStatus() const; BOOL GetAsSystemTime(SYSTEMTIME& sysTime) const; int GetYear() const; int GetMonth() const; // month of year (1 = Jan) int GetDay() const; // day of month (0-31) int GetHour() const; // hour in day (0-23) int GetMinute() const; // minute in hour (0-59) int GetSecond() const; // second in minute (0-59) int GetDayOfWeek() const; // 1=Sun, 2=Mon, ..., 7=Sat int GetDayOfYear() const; // days since start of year, Jan 1 = 1 // Operations public: const COleDateTime& operator=(const COleDateTime& dateSrc); const COleDateTime& operator=(const VARIANT& varSrc); const COleDateTime& operator=(DATE dtSrc); const COleDateTime& operator=(const time_t& timeSrc); const COleDateTime& operator=(const SYSTEMTIME& systimeSrc); const COleDateTime& operator=(const FILETIME& filetimeSrc); BOOL operator==(const COleDateTime& date) const; BOOL operator!=(const COleDateTime& date) const; BOOL operator<(const COleDateTime& date) const; BOOL operator>(const COleDateTime& date) const; BOOL operator<=(const COleDateTime& date) const; BOOL operator>=(const COleDateTime& date) const; // DateTime math COleDateTime operator+(const COleDateTimeSpan& dateSpan) const; COleDateTime operator-(const COleDateTimeSpan& dateSpan) const; const COleDateTime& operator+=(const COleDateTimeSpan dateSpan); const COleDateTime& operator-=(const COleDateTimeSpan dateSpan); // DateTimeSpan math COleDateTimeSpan operator-(const COleDateTime& date) const; operator DATE() const; int SetDateTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec); int SetDate(int nYear, int nMonth, int nDay); int SetTime(int nHour, int nMin, int nSec); BOOL ParseDateTime(LPCTSTR lpszDate, DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT); // formatting CString Format(DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT) const; CString Format(LPCTSTR lpszFormat) const; CString Format(UINT nFormatID) const; // Implementation protected: void CheckRange(); friend COleDateTimeSpan; }; 2.2.4 COleDateTimeSpanThe so-called companion class used in conjunction with As with its companion class, 3. ConculsionWell, as you can see the date time world in windows is a bit complex. On the one hand, you have a series of datetimes with their base times defined at epoch. On the other hand you have a few other stuff with their base defined on Jan 1, 1900 while still we have one that goes all the way back to 1601. We even have a class that doesn't support DayLight Savings Time and
we also have the I am not exactly sure of the reasons behind these decisions, but nevertheless, when working with these various datatypes and classes, you have to take some extra care and spend a few minutes thinking about what you are doing.
|
||||||||||||||||||||||