PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/plugins/winamp/comdate.h

https://github.com/Erkan-Yilmaz/lastfm-desktop
C Header | 1097 lines | 771 code | 199 blank | 127 comment | 80 complexity | 0f8edcefa7a954b8b2fa2cb49a214399 MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause
  1. // comdate.h
  2. /////////////////////////////////////////////////////////////////////////////
  3. // Copyright (c) 1998-2000 Chris Sells
  4. // All rights reserved.
  5. //
  6. // NO WARRANTIES ARE EXTENDED. USE AT YOUR OWN RISK.
  7. //
  8. // To contact the author with suggestions or comments, use csells@sellsbrothers.com.
  9. /////////////////////////////////////////////////////////////////////////////
  10. // History:
  11. // 9/27/01 - Dropped in operator SYSTEMTIME() and operator FILETIME() from
  12. // Scott Zionic [Scott.Zionic@petersweb.com]. Thanks, Scott.
  13. // 4/9/01 - Implemented operator time_t() and operator struct tm() as per
  14. // Shawn Wildermuth's request.
  15. // 2/8/01 - Fixed a rounding bug in CComSpan reported by Ralf Mohaupt
  16. // [r.mohaupt@lit.lineas.de].
  17. // 11/4/00 - Moved everything to the header file for convenience.
  18. // 4/13/00 - Sudhakar M [msudhakar@yahoo.com] contributed
  19. // CComDATE(const struct tm& tmSrc), from which I also extrapolated
  20. // CComDATE::operator=(const struct tm& tmSrc).
  21. // 3/10/00 - Inspired by Eric White [EricW@DATA-TECH.COM] to add an
  22. // operator DBTIMESTAMP using his implementation. Also added
  23. // extra ctor, operator= and conversion operators for other date/time
  24. // formats, but haven't implemented all of them yet.
  25. // Inspired by Artyom Tyazhelov [artyom6@hotmail.com] to
  26. // leave current time alone when calling SetDate and leaving current
  27. // date alone when calling SetTime.
  28. // 1/15/00 - Fixed a 2038 bug in Now. Thanks Michael Entin [entin@swusa.com].
  29. // 7/14/99 - Fixed a linker problem w/ some inline functions release
  30. // builds. Thanks to David Maw [David.Maw@unisys.com] for
  31. // first pointing it out.
  32. // 6/9/99 - Fixed a problem in Maketm where tm_isdst was not being set
  33. // (as is required by the CRT). Thanks to Jim Hoffman
  34. // [JHoffman@Enerx.com] for pointing it out.
  35. // 4/18/99 - Fixed a problem in Format to provide a work-around in the
  36. // VC6 implementation of wcsftime. Thanks for Joe O'Leary for
  37. // pointing it out.
  38. // Even better, Joe also contributed FormatDate and FormatTime
  39. // to wrap the National Language Support functions GetTimeFormat()
  40. // and GetDateFormat(). Thanks, Joe!
  41. // Also, Juan Rivera (juanc@kodak.com) pointed out a missing operator=
  42. // declaration. Thanks, Juan.
  43. // 12/24/98 - Based on a suggestion by Ronald Laeremans [RonaldL@mvps.org],
  44. // replaced all of the manual Maketm code w/ VariantToSystemTime.
  45. // Also updated MakeDATE to use SystemTimeToVariantTime. Thanks, Ron!
  46. // 12/23/98 - Fixed a bug Ward pointed out in CComDATE::operator=(const time_t&).
  47. // 12/21/98 - Ward Fuller <wfuller@tsisoft.com> pointed out a BSTR leak in
  48. // the Format implementation. It's plugged. Thanks, Ward!
  49. // 12/21/98 - Initial release.
  50. /////////////////////////////////////////////////////////////////////////////
  51. // The file provides two class for use with dates and times under Windows.
  52. //
  53. // CComDATE: Wraps the COM DATE type, providing conversions from VARIANT,
  54. // DATE, ANSI string, UNICODE string, time_t, SYSTEMTIME, FILETIME,
  55. // DOS time and DBTIMESTAMP data types.
  56. //
  57. // CComSpan: Represents the result of subtracting one CComDATE from another.
  58. // Useful for time/date math.
  59. //
  60. // NOTE: This usage of these classes are based loosely on the MFC classes
  61. // COleDateTime and COleDateTimeSpan. However, the implementation is 99% mine.
  62. #pragma once
  63. #ifndef __COMDATE_H__
  64. #define __COMDATE_H__
  65. #include <time.h>
  66. #include <limits.h>
  67. #include <tchar.h>
  68. #include <math.h> // ceil, floor and modf
  69. #include <winnls.h>
  70. #include <OAIDL.H>
  71. #include <crtdbg.h>
  72. /////////////////////////////////////////////////////////////////////////////
  73. // CComDATE class
  74. class CComSpan; // Forward declaration
  75. class CComDATE
  76. {
  77. public:
  78. static CComDATE Now();
  79. static bool IsValidDate(const DATE& dt);
  80. CComDATE();
  81. CComDATE(const CComDATE& dtSrc);
  82. CComDATE(const VARIANT& varSrc);
  83. CComDATE(DATE dtSrc);
  84. CComDATE(const char* pszSrc);
  85. CComDATE(const wchar_t* pszSrc);
  86. CComDATE(time_t timeSrc);
  87. CComDATE(const struct tm& tmSrc);
  88. CComDATE(const SYSTEMTIME& systimeSrc);
  89. CComDATE(const FILETIME& filetimeSrc);
  90. CComDATE(long nYear, long nMonth, long nDay, long nHour = 0, long nMin = 0, long nSec = 0);
  91. CComDATE(WORD wDosDate, WORD wDosTime);
  92. #ifdef __oledb_h__
  93. CComDATE(const DBTIMESTAMP& dbts);
  94. #endif
  95. public:
  96. bool IsValid() const;
  97. long Year() const;
  98. long Month() const; // month of year (1 = Jan)
  99. long Day() const; // day of month (1-31)
  100. long Hour() const; // hour in day (0-23)
  101. long Minute() const; // minute in hour (0-59)
  102. long Second() const; // second in minute (0-59)
  103. long DayOfWeek() const; // 1=Sun, 2=Mon, ..., 7=Sat
  104. long DayOfYear() const; // days since start of year, Jan 1 = 1
  105. bool IsLeapYear() const; // Whether it's a leap year or not
  106. bool IsNoon() const; // Whether it's 12:00:00pm or not
  107. bool IsMidnight() const; // Whether it's 12:00:00am or not
  108. // Operations
  109. public:
  110. const CComDATE& operator=(const CComDATE& dtSrc);
  111. const CComDATE& operator=(const VARIANT& varSrc);
  112. const CComDATE& operator=(DATE dtSrc);
  113. const CComDATE& operator=(const char* pszSrc);
  114. const CComDATE& operator=(const wchar_t* pszSrc);
  115. const CComDATE& operator=(const time_t& timeSrc);
  116. const CComDATE& operator=(const struct tm& tmSrc);
  117. const CComDATE& operator=(const SYSTEMTIME& systimeSrc);
  118. const CComDATE& operator=(const FILETIME& filetimeSrc);
  119. #ifdef __oledb_h__
  120. const CComDATE& CComDATE::operator=(const DBTIMESTAMP& dbts);
  121. #endif
  122. bool operator==(const CComDATE& date) const;
  123. bool operator!=(const CComDATE& date) const;
  124. bool operator<(const CComDATE& date) const;
  125. bool operator>(const CComDATE& date) const;
  126. bool operator<=(const CComDATE& date) const;
  127. bool operator>=(const CComDATE& date) const;
  128. // Date math
  129. const CComDATE& operator+=(const CComSpan& span);
  130. const CComDATE& operator-=(const CComSpan& span);
  131. friend CComDATE operator+(const CComDATE& date, const CComSpan& span);
  132. friend CComDATE operator-(const CComDATE& date, const CComSpan& span);
  133. friend CComDATE operator+(const CComSpan& span, const CComDATE& date);
  134. friend CComSpan operator-(const CComDATE& date1, const CComDATE& date2);
  135. operator DATE() const;
  136. DATE* operator&();
  137. operator VARIANT() const;
  138. operator time_t() const;
  139. operator struct tm() const;
  140. operator SYSTEMTIME() const;
  141. operator FILETIME() const;
  142. #ifdef __oledb_h__
  143. operator DBTIMESTAMP() const;
  144. #endif
  145. bool SetDateTime(long nYear, long nMonth, long nDay, long nHour, long nMin, long nSec);
  146. bool SetDate(long nYear, long nMonth, long nDay);
  147. bool SetTime(long nHour, long nMin, long nSec);
  148. bool ParseDateTime(const char* lpszDate, DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT);
  149. bool ParseDateTime(const wchar_t* lpszDate, DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT);
  150. // Formatting
  151. LPTSTR Format(LPTSTR pszOut, DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT) const;
  152. LPTSTR Format(LPTSTR pszOut, LPCTSTR lpszFormat) const;
  153. #ifdef __ATLCOM_H__
  154. LPTSTR Format(LPTSTR pszOut, UINT nFormatID, HINSTANCE hinst = _Module.GetResourceInstance()) const;
  155. #else
  156. LPTSTR Format(LPTSTR pszOut, UINT nFormatID, HINSTANCE hinst = GetModuleHandle(0)) const;
  157. #endif
  158. // Formatting using National Language Support functions GetTimeFormat() and GetDateFormat()
  159. LPTSTR FormatTime(LPTSTR pszOut, LPCTSTR szFmt=NULL, DWORD dwFlags=0, LCID lcid=LOCALE_USER_DEFAULT) const;
  160. LPTSTR FormatDate(LPTSTR pszOut, LPCTSTR szFmt=NULL, DWORD dwFlags=0, LCID lcid=LOCALE_USER_DEFAULT) const;
  161. protected:
  162. enum
  163. {
  164. COMDATE_ERROR = INT_MIN,
  165. MIN_DATE = -657434L, // About year 100
  166. MAX_DATE = 2958465L, // About year 9999
  167. INVALID_DATE = (MIN_DATE-1), // Used to indicate invalid date
  168. };
  169. protected:
  170. DATE m_date;
  171. protected:
  172. void Invalidate();
  173. };
  174. /////////////////////////////////////////////////////////////////////////////
  175. // CComSpan class
  176. class CComSpan
  177. {
  178. public:
  179. CComSpan();
  180. CComSpan(double dblSpanSrc);
  181. CComSpan(const CComSpan& dateSpanSrc);
  182. CComSpan(long nDays, long nHours = 0, long nMins = 0, long nSecs = 0);
  183. bool IsValid() const;
  184. double TotalDays() const; // span in days (about -3.65e6 to 3.65e6)
  185. double TotalHours() const; // span in hours (about -8.77e7 to 8.77e6)
  186. double TotalMinutes() const; // span in minutes (about -5.26e9 to 5.26e9)
  187. double TotalSeconds() const; // span in seconds (about -3.16e11 to 3.16e11)
  188. long Days() const; // component days in span
  189. long Hours() const; // component hours in span (-23 to 23)
  190. long Minutes() const; // component minutes in span (-59 to 59)
  191. long Seconds() const; // component seconds in span (-59 to 59)
  192. public:
  193. const CComSpan& operator=(double dblSpanSrc);
  194. const CComSpan& operator=(const CComSpan& dateSpanSrc);
  195. bool operator==(const CComSpan& dateSpan) const;
  196. bool operator!=(const CComSpan& dateSpan) const;
  197. bool operator<(const CComSpan& dateSpan) const;
  198. bool operator>(const CComSpan& dateSpan) const;
  199. bool operator<=(const CComSpan& dateSpan) const;
  200. bool operator>=(const CComSpan& dateSpan) const;
  201. // Math
  202. const CComSpan& operator+=(const CComSpan& rhs);
  203. const CComSpan& operator-=(const CComSpan& rhs);
  204. CComSpan operator-() const;
  205. friend CComSpan operator+(const CComSpan& span1, const CComSpan& span2);
  206. friend CComSpan operator-(const CComSpan& span1, const CComSpan& span2);
  207. operator double() const;
  208. void SetSpan(long nDays, long nHours, long nMins, long nSecs);
  209. protected:
  210. enum
  211. {
  212. MAX_SPAN = 3615897L,
  213. MIN_SPAN = -MAX_SPAN,
  214. INVALID_SPAN = (MIN_SPAN-1), // Used to indicate invalid span
  215. };
  216. protected:
  217. double m_span;
  218. protected:
  219. void Invalidate();
  220. };
  221. /////////////////////////////////////////////////////////////////////////////
  222. // CComDATE inline implementations
  223. inline bool CComDATE::IsValidDate(const DATE& dt)
  224. {
  225. // About year 100 to about 9999
  226. return (dt >= MIN_DATE && dt <= MAX_DATE);
  227. }
  228. inline CComDATE CComDATE::Now()
  229. {
  230. SYSTEMTIME sysTime;
  231. GetLocalTime(&sysTime);
  232. return CComDATE(sysTime);
  233. }
  234. inline CComDATE::CComDATE()
  235. { Invalidate(); }
  236. inline CComDATE::CComDATE(const CComDATE& dtSrc)
  237. { m_date = dtSrc.m_date; }
  238. inline CComDATE::CComDATE(const VARIANT& varSrc)
  239. { *this = varSrc; }
  240. inline CComDATE::CComDATE(DATE dtSrc)
  241. { m_date = dtSrc; }
  242. inline CComDATE::CComDATE(const char* pszSrc)
  243. { ParseDateTime(pszSrc); }
  244. inline CComDATE::CComDATE(const wchar_t* pszSrc)
  245. { ParseDateTime(pszSrc); }
  246. inline CComDATE::CComDATE(time_t timeSrc)
  247. { *this = timeSrc; }
  248. inline CComDATE::CComDATE(const struct tm& tmSrc)
  249. {
  250. SetDateTime(tmSrc.tm_year + 1900,
  251. tmSrc.tm_mon + 1,
  252. tmSrc.tm_mday,
  253. tmSrc.tm_hour,
  254. tmSrc.tm_min,
  255. tmSrc.tm_sec);
  256. }
  257. inline CComDATE::CComDATE(const SYSTEMTIME& systimeSrc)
  258. { *this = systimeSrc; }
  259. inline CComDATE::CComDATE(const FILETIME& filetimeSrc)
  260. { *this = filetimeSrc; }
  261. inline CComDATE::CComDATE(long nYear, long nMonth, long nDay, long nHour, long nMin, long nSec)
  262. { SetDateTime(nYear, nMonth, nDay, nHour, nMin, nSec); }
  263. inline CComDATE::CComDATE(WORD wDosDate, WORD wDosTime)
  264. { if( !DosDateTimeToVariantTime(wDosDate, wDosTime, &m_date) ) Invalidate(); }
  265. inline const CComDATE& CComDATE::operator=(const CComDATE& dtSrc)
  266. { m_date = dtSrc.m_date; return *this; }
  267. inline const CComDATE& CComDATE::operator=(const char* pszSrc)
  268. { ParseDateTime(pszSrc); return *this; }
  269. inline const CComDATE& CComDATE::operator=(const wchar_t* pszSrc)
  270. { ParseDateTime(pszSrc); return *this; }
  271. inline bool CComDATE::operator==(const CComDATE& date) const
  272. { return (m_date == date.m_date); }
  273. inline bool CComDATE::operator!=(const CComDATE& date) const
  274. { return (m_date != date.m_date); }
  275. inline CComDATE::operator DATE() const
  276. { return m_date; }
  277. inline DATE* CComDATE::operator&()
  278. { return &m_date; }
  279. inline bool CComDATE::SetDate(long nYear, long nMonth, long nDay)
  280. { return SetDateTime(nYear, nMonth, nDay, Hour(), Minute(), Second()); }
  281. inline bool CComDATE::SetTime(long nHour, long nMin, long nSec)
  282. { return SetDateTime(Year(), Month(), Day(), nHour, nMin, nSec); }
  283. inline const CComDATE& CComDATE::operator+=(const CComSpan& span)
  284. { *this = *this + span; return *this; }
  285. inline const CComDATE& CComDATE::operator-=(const CComSpan& span)
  286. { *this = *this - span; return *this; }
  287. inline bool CComDATE::IsValid() const
  288. { return IsValidDate(m_date); }
  289. inline void CComDATE::Invalidate()
  290. { m_date = INVALID_DATE; }
  291. #ifdef __oledb_h__
  292. inline CComDATE::CComDATE(const DBTIMESTAMP& dbts)
  293. { SetDateTime(dbts.year, dbts.month, dbts.day, dbts.hour, dbts.minute, dbts.second); }
  294. inline const CComDATE& CComDATE::operator=(const DBTIMESTAMP& dbts)
  295. { SetDateTime(dbts.year, dbts.month, dbts.day, dbts.hour, dbts.minute, dbts.second); return *this; }
  296. #endif // __oledb_h__
  297. /////////////////////////////////////////////////////////////////////////////
  298. // CComSpan inline implementations
  299. inline CComSpan::CComSpan()
  300. { Invalidate(); }
  301. inline CComSpan::CComSpan(double db) : m_span(db) {}
  302. inline CComSpan::CComSpan(const CComSpan& rhs)
  303. { m_span = rhs.m_span; }
  304. inline CComSpan::CComSpan(long nDays, long nHours, long nMins, long nSecs)
  305. { SetSpan(nDays, nHours, nMins, nSecs); }
  306. inline const CComSpan& CComSpan::operator=(double db)
  307. { m_span = db; return *this; }
  308. inline const CComSpan& CComSpan::operator=(const CComSpan& span)
  309. { m_span = span.m_span; return *this; }
  310. inline double CComSpan::TotalDays() const
  311. { _ASSERTE(IsValid()); return m_span; }
  312. inline double CComSpan::TotalHours() const
  313. { _ASSERTE(IsValid()); return m_span * 24; }
  314. inline double CComSpan::TotalMinutes() const
  315. { _ASSERTE(IsValid()); return m_span * 24 * 60; }
  316. inline double CComSpan::TotalSeconds() const
  317. { _ASSERTE(IsValid()); return m_span * 24 * 60 * 60; }
  318. inline long CComSpan::Days() const
  319. { _ASSERTE(IsValid()); return (long)m_span; }
  320. inline bool CComSpan::operator==(const CComSpan& rhs) const
  321. { return m_span == rhs.m_span; }
  322. inline bool CComSpan::operator!=(const CComSpan& rhs) const
  323. { return m_span != rhs.m_span; }
  324. inline bool CComSpan::operator<(const CComSpan& rhs) const
  325. { return m_span < rhs.m_span; }
  326. inline bool CComSpan::operator>(const CComSpan& rhs) const
  327. { return m_span > rhs.m_span; }
  328. inline bool CComSpan::operator<=(const CComSpan& rhs) const
  329. { return m_span <= rhs.m_span; }
  330. inline bool CComSpan::operator>=(const CComSpan& rhs) const
  331. { return m_span >= rhs.m_span; }
  332. inline const CComSpan& CComSpan::operator+=(const CComSpan& rhs)
  333. { return (*this = *this + rhs); }
  334. inline const CComSpan& CComSpan::operator-=(const CComSpan& rhs)
  335. { return (*this = *this - rhs); }
  336. inline CComSpan CComSpan::operator-() const
  337. { return CComSpan(-m_span); }
  338. inline CComSpan::operator double() const
  339. { return m_span; }
  340. inline bool CComSpan::IsValid() const
  341. { return (m_span >= MIN_SPAN && m_span <= MAX_SPAN); }
  342. inline void CComSpan::Invalidate()
  343. { m_span = INVALID_SPAN; }
  344. /////////////////////////////////////////////////////////////////////////////
  345. // CComDATE class helper definitions
  346. #define HALF_SECOND 1.0/172800.0 // Half a second, expressed in days
  347. bool MakeDATE(DATE* pdtDest, WORD wYear, WORD wMonth, WORD wDay, WORD wHour, WORD wMinute, WORD wSecond);
  348. bool Maketm(struct tm* ptmDest, DATE dtSrc);
  349. double DATEAsDouble(DATE dtSrc);
  350. DATE MakeDATE(double dbSrc);
  351. /////////////////////////////////////////////////////////////////////////////
  352. // CComDATE class
  353. inline
  354. long CComDATE::Year() const
  355. {
  356. struct tm tmDest;
  357. if( IsValid() && Maketm(&tmDest, m_date) ) return tmDest.tm_year + 1900;
  358. return COMDATE_ERROR;
  359. }
  360. inline
  361. long CComDATE::Month() const
  362. {
  363. struct tm tmDest;
  364. if( IsValid() && Maketm(&tmDest, m_date) ) return tmDest.tm_mon + 1;
  365. return COMDATE_ERROR;
  366. }
  367. inline
  368. long CComDATE::Day() const
  369. {
  370. struct tm tmDest;
  371. if( IsValid() && Maketm(&tmDest, m_date) ) return tmDest.tm_mday;
  372. return COMDATE_ERROR;
  373. }
  374. inline
  375. long CComDATE::Hour() const
  376. {
  377. struct tm tmDest;
  378. if( IsValid() && Maketm(&tmDest, m_date) ) return tmDest.tm_hour;
  379. return COMDATE_ERROR;
  380. }
  381. inline
  382. long CComDATE::Minute() const
  383. {
  384. struct tm tmDest;
  385. if( IsValid() && Maketm(&tmDest, m_date) ) return tmDest.tm_min;
  386. return COMDATE_ERROR;
  387. }
  388. inline
  389. long CComDATE::Second() const
  390. {
  391. struct tm tmDest;
  392. if( IsValid() && Maketm(&tmDest, m_date) ) return tmDest.tm_sec;
  393. return COMDATE_ERROR;
  394. }
  395. inline
  396. long CComDATE::DayOfWeek() const
  397. {
  398. struct tm tmDest;
  399. if( IsValid() && Maketm(&tmDest, m_date) ) return tmDest.tm_wday + 1;
  400. return COMDATE_ERROR;
  401. }
  402. inline
  403. long CComDATE::DayOfYear() const
  404. {
  405. struct tm tmDest;
  406. if( IsValid() && Maketm(&tmDest, m_date) ) return tmDest.tm_yday + 1;
  407. return COMDATE_ERROR;
  408. }
  409. inline
  410. bool CComDATE::IsLeapYear() const
  411. {
  412. long year = Year();
  413. return ((year != COMDATE_ERROR) && ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0));
  414. }
  415. inline
  416. bool CComDATE::IsNoon() const
  417. {
  418. return Hour() == 12 && Minute() == 0 && Second() == 0;
  419. }
  420. inline
  421. bool CComDATE::IsMidnight() const
  422. {
  423. return Hour() == 0 && Minute() == 0 && Second() == 0;
  424. }
  425. inline
  426. const CComDATE& CComDATE::operator=(const VARIANT& varSrc)
  427. {
  428. if( varSrc.vt == VT_DATE )
  429. {
  430. m_date = varSrc.date;
  431. }
  432. else
  433. {
  434. VARIANT varDest = { 0 };
  435. if( SUCCEEDED(VariantChangeType(&varDest, const_cast<VARIANT*>(&varSrc), 0, VT_DATE)) )
  436. {
  437. m_date = varDest.date;
  438. VariantClear(&varDest);
  439. }
  440. else
  441. {
  442. Invalidate();
  443. }
  444. }
  445. return *this;
  446. }
  447. inline
  448. const CComDATE& CComDATE::operator=(DATE dtSrc)
  449. {
  450. m_date = dtSrc;
  451. return *this;
  452. }
  453. inline
  454. const CComDATE& CComDATE::operator=(const time_t& tmSrc)
  455. {
  456. // Convert time_t to struct tm
  457. tm *ptm = localtime(&tmSrc);
  458. if( !ptm ||
  459. !MakeDATE(&m_date,
  460. (WORD)(ptm->tm_year + 1900),
  461. (WORD)(ptm->tm_mon + 1),
  462. (WORD)ptm->tm_mday,
  463. (WORD)ptm->tm_hour,
  464. (WORD)ptm->tm_min,
  465. (WORD)ptm->tm_sec) )
  466. {
  467. // Local time must have failed (tmSrc before 1/1/70 12am)
  468. Invalidate();
  469. }
  470. return *this;
  471. }
  472. inline
  473. const CComDATE& CComDATE::operator=(const struct tm& tmSrc)
  474. {
  475. SetDateTime(tmSrc.tm_year + 1900,
  476. tmSrc.tm_mon + 1,
  477. tmSrc.tm_mday,
  478. tmSrc.tm_hour,
  479. tmSrc.tm_min,
  480. tmSrc.tm_sec);
  481. return *this;
  482. }
  483. inline
  484. const CComDATE& CComDATE::operator=(const SYSTEMTIME& systmSrc)
  485. {
  486. if( !MakeDATE(&m_date,
  487. systmSrc.wYear,
  488. systmSrc.wMonth,
  489. systmSrc.wDay,
  490. systmSrc.wHour,
  491. systmSrc.wMinute,
  492. systmSrc.wSecond) )
  493. {
  494. Invalidate();
  495. }
  496. return *this;
  497. }
  498. inline
  499. const CComDATE& CComDATE::operator=(const FILETIME& ftSrc)
  500. {
  501. // Assume UTC FILETIME, so convert to LOCALTIME
  502. FILETIME ftLocal;
  503. if( !FileTimeToLocalFileTime( &ftSrc, &ftLocal) )
  504. {
  505. #ifdef ATLTRACE
  506. ATLTRACE("\nFileTimeToLocalFileTime failed. Error = %lu.\n\t", GetLastError());
  507. #endif
  508. Invalidate();
  509. }
  510. else
  511. {
  512. // Take advantage of SYSTEMTIME -> FILETIME conversion
  513. SYSTEMTIME systime;
  514. // At this polong systime should always be valid, but...
  515. if( !FileTimeToSystemTime(&ftLocal, &systime) ||
  516. !MakeDATE(&m_date,
  517. systime.wYear,
  518. systime.wMonth,
  519. systime.wDay,
  520. systime.wHour,
  521. systime.wMinute,
  522. systime.wSecond) )
  523. {
  524. Invalidate();
  525. }
  526. }
  527. return *this;
  528. }
  529. inline
  530. CComDATE::operator VARIANT() const
  531. {
  532. VARIANT var = { 0 };
  533. var.vt = VT_DATE;
  534. var.date = m_date;
  535. return var;
  536. }
  537. inline
  538. CComDATE::operator time_t() const
  539. {
  540. struct tm tmDest;
  541. if( Maketm(&tmDest, m_date) )
  542. {
  543. return mktime(&tmDest);
  544. }
  545. return -1;
  546. }
  547. inline
  548. CComDATE::operator struct tm() const
  549. {
  550. struct tm tmDest = { 0 };
  551. Maketm(&tmDest, m_date);
  552. return tmDest;
  553. }
  554. inline
  555. CComDATE::operator SYSTEMTIME() const
  556. {
  557. SYSTEMTIME st = { 0 };
  558. VariantTimeToSystemTime(m_date, &st);
  559. return st;
  560. }
  561. inline
  562. CComDATE::operator FILETIME() const
  563. {
  564. FILETIME ft = { 0 };
  565. SYSTEMTIME st;
  566. VariantTimeToSystemTime(m_date, &st);
  567. SystemTimeToFileTime(&st, &ft);
  568. return ft;
  569. }
  570. #ifdef __oledb_h__
  571. inline
  572. CComDATE::operator DBTIMESTAMP() const
  573. {
  574. DBTIMESTAMP dbts = { 0 };
  575. struct tm tmDest;
  576. if( IsValid() && Maketm(&tmDest, m_date) )
  577. {
  578. dbts.day = tmDest.tm_mday;
  579. dbts.month = tmDest.tm_mon + 1;
  580. dbts.year = tmDest.tm_year + 1900;
  581. dbts.hour = tmDest.tm_hour;
  582. dbts.minute = tmDest.tm_min;
  583. dbts.second = tmDest.tm_sec;
  584. }
  585. return dbts;
  586. }
  587. #endif
  588. inline
  589. bool CComDATE::operator<(const CComDATE& date) const
  590. {
  591. _ASSERTE(IsValid());
  592. _ASSERTE(date.IsValid());
  593. // Handle negative dates
  594. return DATEAsDouble(m_date) < DATEAsDouble(date.m_date);
  595. }
  596. inline
  597. bool CComDATE::operator>(const CComDATE& date) const
  598. {
  599. _ASSERTE(IsValid());
  600. _ASSERTE(date.IsValid());
  601. // Handle negative dates
  602. return DATEAsDouble(m_date) > DATEAsDouble(date.m_date);
  603. }
  604. inline
  605. bool CComDATE::operator<=(const CComDATE& date) const
  606. {
  607. _ASSERTE(IsValid());
  608. _ASSERTE(date.IsValid());
  609. // Handle negative dates
  610. return DATEAsDouble(m_date) <= DATEAsDouble(date.m_date);
  611. }
  612. inline
  613. bool CComDATE::operator>=(const CComDATE& date) const
  614. {
  615. _ASSERTE(IsValid());
  616. _ASSERTE(date.IsValid());
  617. // Handle negative dates
  618. return DATEAsDouble(m_date) >= DATEAsDouble(date.m_date);
  619. }
  620. inline
  621. bool CComDATE::SetDateTime(
  622. long nYear,
  623. long nMonth,
  624. long nDay,
  625. long nHour,
  626. long nMin,
  627. long nSec)
  628. {
  629. if( !MakeDATE(&m_date, (WORD)nYear, (WORD)nMonth, (WORD)nDay, (WORD)nHour, (WORD)nMin, (WORD)nSec) )
  630. {
  631. Invalidate();
  632. }
  633. return IsValid();
  634. }
  635. /*inline
  636. bool CComDATE::ParseDateTime(const char* lpszDate, DWORD dwFlags, LCID lcid)
  637. {
  638. USES_CONVERSION;
  639. return ParseDateTime(A2OLE(lpszDate), dwFlags, lcid);
  640. }*/
  641. inline
  642. bool CComDATE::ParseDateTime(const wchar_t* lpszDate, DWORD dwFlags, LCID lcid)
  643. {
  644. if( FAILED(VarDateFromStr(const_cast<wchar_t*>(lpszDate), lcid, dwFlags, &m_date)) )
  645. {
  646. Invalidate();
  647. }
  648. return IsValid();
  649. }
  650. inline
  651. LPTSTR CComDATE::Format(LPTSTR pszOut, DWORD dwFlags, LCID lcid) const
  652. {
  653. *pszOut = 0;
  654. // If invalild, return empty string
  655. if (!IsValid()) return pszOut;
  656. BSTR bstr = 0;
  657. if( SUCCEEDED(VarBstrFromDate(m_date, lcid, dwFlags, &bstr)) )
  658. {
  659. #ifdef _UNICODE
  660. wcscpy(pszOut, bstr);
  661. #else
  662. wcstombs(pszOut, bstr, wcslen(bstr) + 1);
  663. #endif
  664. SysFreeString(bstr);
  665. }
  666. return pszOut;
  667. }
  668. inline
  669. LPTSTR CComDATE::Format(LPTSTR pszOut, LPCTSTR pFormat) const
  670. {
  671. *pszOut = 0;
  672. // If invalild, return empty string
  673. struct tm tmDest;
  674. if (!IsValid() || !Maketm(&tmDest, m_date) ) return pszOut;
  675. // Fill in the buffer, disregard return value as it's not necessary
  676. // NOTE: 4096 is an arbitrary value picked lower than INT_MAX
  677. // as the VC6 implementation of wcsftime allocates memory based
  678. // on the 2nd parameter for some reason.
  679. _tcsftime(pszOut, 4096, pFormat, &tmDest);
  680. return pszOut;
  681. }
  682. inline
  683. LPTSTR CComDATE::Format(LPTSTR pszOut, UINT nFormatID, HINSTANCE hinst) const
  684. {
  685. *pszOut = 0;
  686. TCHAR sz[256];
  687. if( LoadString(hinst, nFormatID, sz, sizeof(sz)/sizeof(*sz)) )
  688. {
  689. return Format(pszOut, sz);
  690. }
  691. return pszOut;
  692. }
  693. // The FormatDate and FormatTime functions were provided by Joe O'Leary (joleary@artisoft.com) to
  694. // wrap he Win32 National Language Support functions ::GetDateFormat() and ::GetTimeFormat().
  695. // The format strings used here are specified in the on-line help for those functions.
  696. // The default format is the current user locale.
  697. inline
  698. LPTSTR CComDATE::FormatDate(LPTSTR pszOut, LPCTSTR szFmt, DWORD dwFlags, LCID lcid) const
  699. {
  700. _ASSERTE((szFmt==NULL) || (dwFlags==0));// if format is non-NULL, 'dwFlags' MUST be zero
  701. SYSTEMTIME st;
  702. memset(&st, 0, sizeof(SYSTEMTIME));
  703. *pszOut = NULL;
  704. if ( !VariantTimeToSystemTime(m_date, &st) )
  705. {
  706. #ifdef ATLTRACE
  707. ATLTRACE("\nVariantTimeToSystemTime failed. Error = %lu.\n\t", GetLastError());
  708. #endif
  709. }
  710. else if ( GetDateFormat(lcid, dwFlags, &st, szFmt, pszOut, 255) == 0 )
  711. {
  712. #ifdef ATLTRACE
  713. ATLTRACE("\nGetDateFormat failed. Error = %lu.\n\t", GetLastError());
  714. #endif
  715. }
  716. return pszOut;
  717. }
  718. inline
  719. LPTSTR CComDATE::FormatTime(LPTSTR pszOut, LPCTSTR szFmt, DWORD dwFlags, LCID lcid) const
  720. {
  721. _ASSERTE((szFmt==NULL) || (dwFlags==0));// if format is non-NULL, 'dwFlags' MUST be zero
  722. SYSTEMTIME st;
  723. memset(&st, 0, sizeof(SYSTEMTIME));
  724. *pszOut = NULL;
  725. if ( !VariantTimeToSystemTime(m_date, &st) )
  726. {
  727. #ifdef ATLTRACE
  728. ATLTRACE("\nVariantTimeToSystemTime failed. Error = %lu.\n\t", GetLastError());
  729. #endif
  730. }
  731. else if ( GetTimeFormat(lcid, dwFlags, &st, szFmt, pszOut, 255) == 0 )
  732. {
  733. #ifdef ATLTRACE
  734. ATLTRACE("\nGetTimeFormat failed. Error = %lu.\n\t", GetLastError());
  735. #endif
  736. }
  737. return pszOut;
  738. }
  739. inline
  740. bool Maketm(struct tm* ptmDest, DATE dtSrc)
  741. {
  742. SYSTEMTIME st;
  743. if( !VariantTimeToSystemTime(dtSrc, &st) ) return false;
  744. struct tm& tmDest = *ptmDest; // Convenience
  745. tmDest.tm_sec = st.wSecond;
  746. tmDest.tm_min = st.wMinute;
  747. tmDest.tm_hour = st.wHour;
  748. tmDest.tm_mday = st.wDay;
  749. tmDest.tm_mon = st.wMonth - 1;
  750. tmDest.tm_year = st.wYear - 1900;
  751. tmDest.tm_wday = st.wDayOfWeek;
  752. tmDest.tm_isdst = -1; // Force DST checking
  753. mktime(&tmDest); // Normalize
  754. return true;
  755. }
  756. inline
  757. double DATEAsDouble(DATE dt)
  758. {
  759. // No problem if positive
  760. if (dt >= 0) return dt;
  761. // If negative, must convert since negative dates not continuous
  762. // (examples: -1.25 to -.75, -1.50 to -.50, -1.75 to -.25)
  763. double temp = ceil(dt);
  764. return temp - (dt - temp);
  765. }
  766. inline
  767. DATE MakeDATE(double dbl)
  768. {
  769. // No problem if positive
  770. if (dbl >= 0) return dbl;
  771. // If negative, must convert since negative dates not continuous
  772. // (examples: -.75 to -1.25, -.50 to -1.50, -.25 to -1.75)
  773. double temp = floor(dbl); // dbl is now whole part
  774. return temp + (temp - dbl);
  775. }
  776. inline
  777. bool MakeDATE(
  778. DATE* pdtDest,
  779. WORD wYear,
  780. WORD wMonth,
  781. WORD wDay,
  782. WORD wHour,
  783. WORD wMinute,
  784. WORD wSecond)
  785. {
  786. SYSTEMTIME st = { 0 };
  787. st.wYear = wYear;
  788. st.wMonth = wMonth;
  789. st.wDay = wDay;
  790. st.wHour = wHour;
  791. st.wMinute = wMinute;
  792. st.wSecond = wSecond;
  793. return SystemTimeToVariantTime(&st, pdtDest) ? true : false;
  794. }
  795. /////////////////////////////////////////////////////////////////////////////
  796. // CComSpan class
  797. inline
  798. long CComSpan::Hours() const
  799. {
  800. _ASSERTE(IsValid());
  801. // Truncate days and scale up
  802. double dbTemp = modf(m_span, &dbTemp);
  803. return (long)(dbTemp * 24);
  804. }
  805. inline
  806. long CComSpan::Minutes() const
  807. {
  808. _ASSERTE(IsValid());
  809. // Truncate hours and scale up
  810. double dbTemp = modf(m_span * 24, &dbTemp);
  811. return (long)((dbTemp + HALF_SECOND) * 60);
  812. }
  813. inline
  814. long CComSpan::Seconds() const
  815. {
  816. _ASSERTE(IsValid());
  817. // Truncate minutes and scale up
  818. double dbTemp = modf(m_span * 24 * 60, &dbTemp);
  819. return (long)(dbTemp * 60);
  820. }
  821. inline
  822. void CComSpan::SetSpan(
  823. long nDays,
  824. long nHours,
  825. long nMins,
  826. long nSecs)
  827. {
  828. // Set date span by breaking longo fractional days (all input ranges valid)
  829. m_span = nDays +
  830. ((double)nHours)/24 +
  831. ((double)nMins)/(24*60) +
  832. ((double)nSecs)/(24*60*60);
  833. }
  834. /////////////////////////////////////////////////////////////////////////////
  835. // CComDATE/CComSpan math friend functions
  836. // date2 = date1 + span;
  837. inline
  838. CComDATE operator+(const CComDATE& date1, const CComSpan& span)
  839. {
  840. CComDATE date2;
  841. if( date1.IsValid() && span.IsValid() )
  842. {
  843. // Compute the actual date difference by adding underlying data
  844. date2 = MakeDATE(DATEAsDouble(static_cast<DATE>(date1)) + static_cast<double>(span));
  845. }
  846. return date2;
  847. }
  848. // date2 = span + date1;
  849. inline
  850. CComDATE operator+(const CComSpan& span, const CComDATE& date1)
  851. {
  852. CComDATE date2;
  853. if( date1.IsValid() && span.IsValid() )
  854. {
  855. // Compute the actual date difference by adding underlying data
  856. date2 = MakeDATE(DATEAsDouble(static_cast<DATE>(date1)) + static_cast<double>(span));
  857. }
  858. return date2;
  859. }
  860. // date2 = date1 - span;
  861. inline
  862. CComDATE operator-(const CComDATE& date1, const CComSpan& span)
  863. {
  864. CComDATE date2;
  865. if( date1.IsValid() && span.IsValid() )
  866. {
  867. // Compute the actual date difference by adding underlying data
  868. date2 = MakeDATE(DATEAsDouble(static_cast<DATE>(date1)) - static_cast<double>(span));
  869. }
  870. return date2;
  871. }
  872. // span = date1 - date2;
  873. inline
  874. CComSpan operator-(const CComDATE& date1, const CComDATE& date2)
  875. {
  876. CComSpan span;
  877. if( date1.IsValid() && date2.IsValid() )
  878. {
  879. span = DATEAsDouble(static_cast<DATE>(date1)) - DATEAsDouble(static_cast<DATE>(date2));
  880. }
  881. return span;
  882. }
  883. // span3 = span1 + span2;
  884. inline
  885. CComSpan operator+(const CComSpan& span1, const CComSpan& span2)
  886. {
  887. CComSpan span3;
  888. if( span1.IsValid() && span2.IsValid() ) span3 = span1.m_span + span2.m_span;
  889. return span3;
  890. }
  891. // span3 = span1 - span2;
  892. inline
  893. CComSpan operator-(const CComSpan& span1, const CComSpan& span2)
  894. {
  895. return span1 + (-span2);
  896. }
  897. #undef HALF_SECOND
  898. #endif // __COMDATE_H__