Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

321 lines
8.6 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: time.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes: None.
  11. //
  12. // Functions: None.
  13. //
  14. // History: 09-Sep-95 EricB Created.
  15. // 01-Dec-95 MarkBl Split from util.cxx.
  16. //
  17. //----------------------------------------------------------------------------
  18. #include "..\pch\headers.hxx"
  19. #pragma hdrstop
  20. #include <mstask.h>
  21. #include "..\inc\common.hxx"
  22. #include "..\inc\debug.hxx"
  23. #include "..\inc\time.hxx"
  24. //+-------------------------------------------------------------------------
  25. //
  26. // Function: IsLeapYear
  27. //
  28. // Synopsis: Determines if a given year is a leap year.
  29. //
  30. // Arguments: [wYear] - the year
  31. //
  32. // Returns: boolean value: TRUE == leap year
  33. //
  34. // History: 05-05-93 EricB
  35. //
  36. // BUGBUG: kevinro sez that there were no regular leap years prior to 1904!
  37. //--------------------------------------------------------------------------
  38. BOOL
  39. IsLeapYear(WORD wYear)
  40. {
  41. return wYear % 4 == 0 && wYear % 100 != 0 || wYear % 400 == 0;
  42. }
  43. //+----------------------------------------------------------------------------
  44. //
  45. // Function: IsValidDate
  46. //
  47. // Synopsis: Checks for valid values.
  48. //
  49. //-----------------------------------------------------------------------------
  50. BOOL
  51. IsValidDate(WORD wMonth, WORD wDay, WORD wYear)
  52. {
  53. if (wMonth < JOB_MIN_MONTH || wMonth > JOB_MAX_MONTH ||
  54. wDay < JOB_MIN_DAY)
  55. {
  56. return FALSE;
  57. }
  58. if (wMonth == JOB_MONTH_FEBRUARY && IsLeapYear(wYear))
  59. {
  60. if (wDay > (g_rgMonthDays[JOB_MONTH_FEBRUARY] + 1))
  61. {
  62. return FALSE;
  63. }
  64. }
  65. else
  66. {
  67. if (wDay > g_rgMonthDays[wMonth])
  68. {
  69. return FALSE;
  70. }
  71. }
  72. return TRUE;
  73. }
  74. //+----------------------------------------------------------------------------
  75. //
  76. // Function: MonthDays
  77. //
  78. // Synopsis: Returns the number of days in the indicated month.
  79. //
  80. // Arguments: [wMonth] - Index of the month in question where January = 1
  81. // through December equalling 12.
  82. // [yYear] - If non-zero, then leap year adjustment for February
  83. // will be applied.
  84. // [pwDays] - The place to return the number of days in the
  85. // indicated month.
  86. //
  87. // Returns: S_OK or E_INVALIDARG
  88. //
  89. // History: 10-29-93 EricB
  90. //
  91. //-----------------------------------------------------------------------------
  92. HRESULT
  93. MonthDays(WORD wMonth, WORD wYear, WORD *pwDays)
  94. {
  95. if (wMonth < JOB_MIN_MONTH || wMonth > JOB_MAX_MONTH)
  96. {
  97. return E_INVALIDARG;
  98. }
  99. *pwDays = g_rgMonthDays[wMonth];
  100. //
  101. // If February, adjust for leap years
  102. //
  103. if (wMonth == 2 && wYear != 0)
  104. {
  105. if (IsLeapYear(wYear))
  106. {
  107. (*pwDays)++;
  108. }
  109. }
  110. return S_OK;
  111. }
  112. //+----------------------------------------------------------------------------
  113. //
  114. // Function: IncrementDay
  115. //
  116. // Synopsis: increases the SYSTEMTIME day value by one and corrects for
  117. // overflow
  118. //
  119. // Arguments: [pst] - the date to increment
  120. //
  121. //-----------------------------------------------------------------------------
  122. void
  123. IncrementDay(LPSYSTEMTIME pst)
  124. {
  125. pst->wDay++;
  126. WORD wLastDay;
  127. HRESULT hr = MonthDays(pst->wMonth, pst->wYear, &wLastDay);
  128. if (FAILED(hr))
  129. {
  130. schAssert(!"Bad systemtime");
  131. }
  132. else
  133. {
  134. if (pst->wDay > wLastDay)
  135. {
  136. //
  137. // Wrap to the next month.
  138. //
  139. pst->wDay = 1;
  140. IncrementMonth(pst);
  141. }
  142. }
  143. }
  144. #ifdef YANK
  145. //+----------------------------------------------------------------------------
  146. //
  147. // Member: CTimeList::MakeSysTimeArray
  148. //
  149. // Synopsis: returns the file time list as an array of SYSTEMTIME structs
  150. //
  151. // Arguments: [prgst] - a pointer to an array of filetime structs
  152. // [pCount] - a place to leave the count of array elements. If
  153. // this param is non-zero on entry, this places an
  154. // upper limit on the number returned.
  155. //
  156. //-----------------------------------------------------------------------------
  157. HRESULT
  158. CTimeList::MakeSysTimeArray(LPSYSTEMTIME * prgst, WORD * pCount)
  159. {
  160. WORD cLimit = USHRT_MAX;
  161. if (*pCount > 0)
  162. {
  163. cLimit = *pCount;
  164. }
  165. LPSYSTEMTIME rgst;
  166. *prgst = NULL;
  167. *pCount = 0;
  168. CTimeNode * pCur = m_ptnHead;
  169. while (pCur)
  170. {
  171. rgst = (LPSYSTEMTIME)CoTaskMemRealloc(*prgst,
  172. (*pCount + 1) * sizeof(SYSTEMTIME));
  173. if (rgst == NULL)
  174. {
  175. *pCount = 0;
  176. if (*prgst)
  177. {
  178. CoTaskMemFree(*prgst);
  179. *prgst = NULL;
  180. }
  181. return E_OUTOFMEMORY;
  182. }
  183. FileTimeToSystemTime(&pCur->m_ft, rgst + *pCount);
  184. *prgst = rgst;
  185. if (*pCount >= cLimit)
  186. {
  187. return S_OK;
  188. }
  189. (*pCount)++;
  190. pCur = pCur->Next();
  191. }
  192. return S_OK;
  193. }
  194. //+----------------------------------------------------------------------------
  195. //
  196. // Gregorian calendar functions
  197. //
  198. //-----------------------------------------------------------------------------
  199. //+-------------------------------------------------------------------------
  200. //
  201. // Function: MakeDate
  202. //
  203. // Synopsis: Turns the given Julian Day number into a Gregorian calendar
  204. // date.
  205. //
  206. // Arguments: [lDayNum] - the long Julian Day value.
  207. // [pwMonth] [pwDay] [pwYear] pointers to calendar part vars which
  208. // can be NULL if the part is not needed.
  209. //
  210. // History: 05-05-93 EricB
  211. //
  212. // Notes: Adapted from the FORTRAN code that implements the algorithm
  213. // presented by Fliegl and Van Flanders in Communications of
  214. // the ACM, Vol. 11, No. 10, October, 1968, pg. 657.
  215. //
  216. //--------------------------------------------------------------------------
  217. void
  218. MakeDate(long lDayNum, WORD *pwMonth, WORD *pwDay, WORD *pwYear)
  219. {
  220. long t1 = lDayNum + 68569L;
  221. long t2 = 4L * t1 / 146097L;
  222. t1 = t1 - (146097L * t2 + 3L) / 4L;
  223. long yr = 4000L * (t1 + 1) / 1461001L;
  224. t1 = t1 - 1461L * yr / 4L + 31;
  225. long mo = 80L * t1 / 2447L;
  226. if (pwDay != NULL)
  227. {
  228. *pwDay = (WORD)(t1 - 2447L * mo / 80L);
  229. }
  230. t1 = mo / 11L;
  231. if (pwMonth != NULL)
  232. {
  233. *pwMonth = (WORD)(mo + 2L - 12L * t1);
  234. }
  235. if (pwYear != NULL)
  236. {
  237. *pwYear = (WORD)(100L * (t2 - 49L) + yr + t1);
  238. }
  239. }
  240. //+-------------------------------------------------------------------------
  241. //
  242. // Function: MakeJulianDayNumber
  243. //
  244. // Synopsis: Turns a m/d/y value (from the Gregorian calendar) into its
  245. // Julian Day number.
  246. //
  247. // Arguments: [wMonth] - the month value
  248. // [wDay] - the day value
  249. // [wYear] - the year value
  250. // [plDayNum] - a pointer to a long to receive the result.
  251. //
  252. // Returns: S_OK or E_INVALIDARG
  253. //
  254. // History: 05-04-93 EricB
  255. //
  256. // Notes: Same attribution as MakeDate above.
  257. //
  258. //--------------------------------------------------------------------------
  259. HRESULT
  260. MakeJulianDayNumber(WORD wMonth, WORD wDay, WORD wYear, long *plDayNum)
  261. {
  262. BOOL fLeap = IsLeapYear(wYear);
  263. if ((wMonth < GREG_MINMONTH) ||
  264. (wMonth > GREG_MAXMONTH) ||
  265. (wDay < 1) ||
  266. ((wDay > g_rgMonthDays[wMonth]) &&
  267. !((wMonth == 2) && (wDay == 29) && fLeap)))
  268. {
  269. schDebugOut((DEB_ERROR, "MakeJulDay: invalid date %u/%u/%u.\n",
  270. wMonth, wDay, wYear));
  271. return E_INVALIDARG;
  272. }
  273. long lMonth = (long)wMonth, // assign to longs instead of
  274. lDay = (long)wDay, // copious casting
  275. lYear = (long)wYear;
  276. *plDayNum = lDay - 32075L +
  277. 1461L * (lYear + 4800L + (lMonth - 14L) / 12L) / 4L +
  278. 367L * (lMonth - 2L - (lMonth - 14L) / 12L * 12L) / 12L -
  279. 3L * ((lYear + 4900L + (lMonth - 14L) / 12L) / 100L) / 4L;
  280. return S_OK;
  281. }
  282. //+-------------------------------------------------------------------------
  283. //
  284. // Function: DayOfWeek
  285. //
  286. // Synopsis: Given a Julian Day number, returns the day of the week.
  287. //
  288. // Arguments: [lDayNum] - the julian day number
  289. //
  290. // Returns: the day of the week with values Monday = 0 ... Sunday = 6
  291. //
  292. // History: 05-05-93 EricB
  293. //
  294. //--------------------------------------------------------------------------
  295. WORD
  296. DayOfWeek(long lDayNum)
  297. {
  298. return (WORD)(lDayNum % 7L);
  299. }
  300. #endif // YANK