windows-nt/Source/XPSP1/NT/admin/services/sched/common/time.cxx
2020-09-26 16:20:57 +08:00

322 lines
8.6 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: time.cxx
//
// Contents:
//
// Classes: None.
//
// Functions: None.
//
// History: 09-Sep-95 EricB Created.
// 01-Dec-95 MarkBl Split from util.cxx.
//
//----------------------------------------------------------------------------
#include "..\pch\headers.hxx"
#pragma hdrstop
#include <mstask.h>
#include "..\inc\common.hxx"
#include "..\inc\debug.hxx"
#include "..\inc\time.hxx"
//+-------------------------------------------------------------------------
//
// Function: IsLeapYear
//
// Synopsis: Determines if a given year is a leap year.
//
// Arguments: [wYear] - the year
//
// Returns: boolean value: TRUE == leap year
//
// History: 05-05-93 EricB
//
// BUGBUG: kevinro sez that there were no regular leap years prior to 1904!
//--------------------------------------------------------------------------
BOOL
IsLeapYear(WORD wYear)
{
return wYear % 4 == 0 && wYear % 100 != 0 || wYear % 400 == 0;
}
//+----------------------------------------------------------------------------
//
// Function: IsValidDate
//
// Synopsis: Checks for valid values.
//
//-----------------------------------------------------------------------------
BOOL
IsValidDate(WORD wMonth, WORD wDay, WORD wYear)
{
if (wMonth < JOB_MIN_MONTH || wMonth > JOB_MAX_MONTH ||
wDay < JOB_MIN_DAY)
{
return FALSE;
}
if (wMonth == JOB_MONTH_FEBRUARY && IsLeapYear(wYear))
{
if (wDay > (g_rgMonthDays[JOB_MONTH_FEBRUARY] + 1))
{
return FALSE;
}
}
else
{
if (wDay > g_rgMonthDays[wMonth])
{
return FALSE;
}
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: MonthDays
//
// Synopsis: Returns the number of days in the indicated month.
//
// Arguments: [wMonth] - Index of the month in question where January = 1
// through December equalling 12.
// [yYear] - If non-zero, then leap year adjustment for February
// will be applied.
// [pwDays] - The place to return the number of days in the
// indicated month.
//
// Returns: S_OK or E_INVALIDARG
//
// History: 10-29-93 EricB
//
//-----------------------------------------------------------------------------
HRESULT
MonthDays(WORD wMonth, WORD wYear, WORD *pwDays)
{
if (wMonth < JOB_MIN_MONTH || wMonth > JOB_MAX_MONTH)
{
return E_INVALIDARG;
}
*pwDays = g_rgMonthDays[wMonth];
//
// If February, adjust for leap years
//
if (wMonth == 2 && wYear != 0)
{
if (IsLeapYear(wYear))
{
(*pwDays)++;
}
}
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Function: IncrementDay
//
// Synopsis: increases the SYSTEMTIME day value by one and corrects for
// overflow
//
// Arguments: [pst] - the date to increment
//
//-----------------------------------------------------------------------------
void
IncrementDay(LPSYSTEMTIME pst)
{
pst->wDay++;
WORD wLastDay;
HRESULT hr = MonthDays(pst->wMonth, pst->wYear, &wLastDay);
if (FAILED(hr))
{
schAssert(!"Bad systemtime");
}
else
{
if (pst->wDay > wLastDay)
{
//
// Wrap to the next month.
//
pst->wDay = 1;
IncrementMonth(pst);
}
}
}
#ifdef YANK
//+----------------------------------------------------------------------------
//
// Member: CTimeList::MakeSysTimeArray
//
// Synopsis: returns the file time list as an array of SYSTEMTIME structs
//
// Arguments: [prgst] - a pointer to an array of filetime structs
// [pCount] - a place to leave the count of array elements. If
// this param is non-zero on entry, this places an
// upper limit on the number returned.
//
//-----------------------------------------------------------------------------
HRESULT
CTimeList::MakeSysTimeArray(LPSYSTEMTIME * prgst, WORD * pCount)
{
WORD cLimit = USHRT_MAX;
if (*pCount > 0)
{
cLimit = *pCount;
}
LPSYSTEMTIME rgst;
*prgst = NULL;
*pCount = 0;
CTimeNode * pCur = m_ptnHead;
while (pCur)
{
rgst = (LPSYSTEMTIME)CoTaskMemRealloc(*prgst,
(*pCount + 1) * sizeof(SYSTEMTIME));
if (rgst == NULL)
{
*pCount = 0;
if (*prgst)
{
CoTaskMemFree(*prgst);
*prgst = NULL;
}
return E_OUTOFMEMORY;
}
FileTimeToSystemTime(&pCur->m_ft, rgst + *pCount);
*prgst = rgst;
if (*pCount >= cLimit)
{
return S_OK;
}
(*pCount)++;
pCur = pCur->Next();
}
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Gregorian calendar functions
//
//-----------------------------------------------------------------------------
//+-------------------------------------------------------------------------
//
// Function: MakeDate
//
// Synopsis: Turns the given Julian Day number into a Gregorian calendar
// date.
//
// Arguments: [lDayNum] - the long Julian Day value.
// [pwMonth] [pwDay] [pwYear] pointers to calendar part vars which
// can be NULL if the part is not needed.
//
// History: 05-05-93 EricB
//
// Notes: Adapted from the FORTRAN code that implements the algorithm
// presented by Fliegl and Van Flanders in Communications of
// the ACM, Vol. 11, No. 10, October, 1968, pg. 657.
//
//--------------------------------------------------------------------------
void
MakeDate(long lDayNum, WORD *pwMonth, WORD *pwDay, WORD *pwYear)
{
long t1 = lDayNum + 68569L;
long t2 = 4L * t1 / 146097L;
t1 = t1 - (146097L * t2 + 3L) / 4L;
long yr = 4000L * (t1 + 1) / 1461001L;
t1 = t1 - 1461L * yr / 4L + 31;
long mo = 80L * t1 / 2447L;
if (pwDay != NULL)
{
*pwDay = (WORD)(t1 - 2447L * mo / 80L);
}
t1 = mo / 11L;
if (pwMonth != NULL)
{
*pwMonth = (WORD)(mo + 2L - 12L * t1);
}
if (pwYear != NULL)
{
*pwYear = (WORD)(100L * (t2 - 49L) + yr + t1);
}
}
//+-------------------------------------------------------------------------
//
// Function: MakeJulianDayNumber
//
// Synopsis: Turns a m/d/y value (from the Gregorian calendar) into its
// Julian Day number.
//
// Arguments: [wMonth] - the month value
// [wDay] - the day value
// [wYear] - the year value
// [plDayNum] - a pointer to a long to receive the result.
//
// Returns: S_OK or E_INVALIDARG
//
// History: 05-04-93 EricB
//
// Notes: Same attribution as MakeDate above.
//
//--------------------------------------------------------------------------
HRESULT
MakeJulianDayNumber(WORD wMonth, WORD wDay, WORD wYear, long *plDayNum)
{
BOOL fLeap = IsLeapYear(wYear);
if ((wMonth < GREG_MINMONTH) ||
(wMonth > GREG_MAXMONTH) ||
(wDay < 1) ||
((wDay > g_rgMonthDays[wMonth]) &&
!((wMonth == 2) && (wDay == 29) && fLeap)))
{
schDebugOut((DEB_ERROR, "MakeJulDay: invalid date %u/%u/%u.\n",
wMonth, wDay, wYear));
return E_INVALIDARG;
}
long lMonth = (long)wMonth, // assign to longs instead of
lDay = (long)wDay, // copious casting
lYear = (long)wYear;
*plDayNum = lDay - 32075L +
1461L * (lYear + 4800L + (lMonth - 14L) / 12L) / 4L +
367L * (lMonth - 2L - (lMonth - 14L) / 12L * 12L) / 12L -
3L * ((lYear + 4900L + (lMonth - 14L) / 12L) / 100L) / 4L;
return S_OK;
}
//+-------------------------------------------------------------------------
//
// Function: DayOfWeek
//
// Synopsis: Given a Julian Day number, returns the day of the week.
//
// Arguments: [lDayNum] - the julian day number
//
// Returns: the day of the week with values Monday = 0 ... Sunday = 6
//
// History: 05-05-93 EricB
//
//--------------------------------------------------------------------------
WORD
DayOfWeek(long lDayNum)
{
return (WORD)(lDayNum % 7L);
}
#endif // YANK