📄 dst.cpp
字号:
switch (g_dwTime)
{
case TIME_ZONE_ID_DAYLIGHT :
DEBUGMSG(ZONE_DST, ( _T("DST: Currently in Daylight Time")));
notificationTime = tzi.StandardDate;
break;
case TIME_ZONE_ID_STANDARD :
DEBUGMSG(ZONE_DST, ( _T("DST: Currently in Standard Time")));
notificationTime = tzi.DaylightDate;
break;
default :
DEBUGMSG(ZONE_DST, (_T("DST: Unknown TimeZone")));
ASSERT(TIME_ZONE_ID_UNKNOWN == dwTZ); //otherwise GetTZInfo is busted
return NULL;
}
if (0 == notificationTime.wYear) //no specific date set - do the math
DST_DetermineChangeDate(¬ificationTime);
//only set events that are in the future
VERIFY(SystemTimeToFileTime(¬ificationTime, (FILETIME *)&llNotification));
GetLocalTime(&curTime);
VERIFY(SystemTimeToFileTime(&curTime, (FILETIME *)&llNow));
if (llNotification > llNow)
{
hEvent = CreateEvent(NULL, FALSE, FALSE, DSTEVENT);
if (hEvent != INVALID_HANDLE_VALUE)
{
if (!CeRunAppAtTime(DSTNOTIFICATION, ¬ificationTime))
{
CloseHandle(hEvent);
hEvent = NULL;
}
}
DEBUGMSG(ZONE_DST, (_T("DST: Set TimeChange Event for %d/%d/%02d at %d:%02d"),
notificationTime.wMonth, notificationTime.wDay, notificationTime.wYear,
notificationTime.wHour, notificationTime.wMinute));
}
return hEvent;
}
/*++
Routine Description:
waits for DST event to be signaled, and optionally re-sets the
time as appropriate.
Arguments:
hEvent - handle to DST event
Return Value:
none
--*/
void DST_WaitForEvents(LPHANDLE DST_handles)
{
// The last event can be NULL if we so check before we give the number of handles
DWORD dwEvent = WaitForMultipleObjects(DST_handles[NUMDSTEVENTS-1] ? NUMDSTEVENTS : NUMDSTEVENTS-1,
DST_handles, FALSE, INFINITE);
// returning from this function causes DST_Init to reset all of our events
// so we need to turn everything off
CeRunAppAtEvent(DSTTIMEZONENOTIFICATION, NOTIFICATION_EVENT_NONE);
CeRunAppAtEvent(DSTTIMENOTIFICATION, NOTIFICATION_EVENT_NONE);
CeRunAppAtTime(DSTNOTIFICATION, 0);
// and ditch the handles
for (int i = 0; i < NUMDSTEVENTS; i++)
{
if (NULL != DST_handles[i])
{
CloseHandle(DST_handles[i]);
DST_handles[i] = NULL;
}
}
switch (dwEvent - WAIT_OBJECT_0)
{
case TZCHANGEEVENT :
case TIMECHANGEEVENT :
{
// need to redetermine whether we are in daylight or standard time
DEBUGMSG(ZONE_DST, (_T("Resetting DST event due to Time, Date, or TZ change")));
DST_SetDaylightOrStandardTime();
}
break;
case DSTCHANGEEVENT :
{
if (DST_Auto())
{
SYSTEMTIME stOld, stNew;
LONGLONG llOld, llNew;
#ifndef TASKMANDSTSAMPLE
TCHAR msg[MAX_DSTMSGLEN];
TCHAR title[MAX_DSTTITLELEN];
#endif //TASKMANDSTSAMPLE
GetLocalTime(&stOld);
SystemTimeToFileTime(&stOld, (FILETIME *)&llOld);
/*
Check the time zone information. It's possible that this information has
changed since the GetTimeZoneInformation call in DST_SetEvent, and
this action needs to be based on the current timezone.
*/
TIME_ZONE_INFORMATION tzi = {0};
GetTimeZoneInformation(&tzi);
/*
If we're going from Daylight to Standard, we need to move the
clock BACK by g_tzDSTBias (60 minutes usually). If we're going
from Standard to Daylight we need to move it forward even though
g_tzDSTBias is 0.
*/
if (TIME_ZONE_ID_DAYLIGHT == g_dwTime) // clock needs to go back - so we add (g_tzDSTBias is always negative)
{
llNew = llOld + (LONGLONG)((LONGLONG)tzi.DaylightBias * FILETIME_TO_MINUTES);
// now flip the time flag because we're just about to change
g_dwTime = TIME_ZONE_ID_STANDARD;
SetDaylightTime(FALSE);
}
else // clock needs to go forward - so we subtract (see above)
{
llNew = llOld - (LONGLONG)((LONGLONG)tzi.DaylightBias * FILETIME_TO_MINUTES);
// now flip the time flag because we're just about to change
g_dwTime = TIME_ZONE_ID_DAYLIGHT;
SetDaylightTime(TRUE);
}
FileTimeToSystemTime((FILETIME *)&llNew, &stNew);
DEBUGMSG(ZONE_DST, (L"TZ Change: Updating clock. Old Time =%d:%02d, New Time =%d:%02d\r\n",
stOld.wHour, stOld.wMinute, stNew.wHour, stNew.wMinute));
SetLocalTime(&stNew);
#ifndef TASKMANDSTSAMPLE
if (DST_ShowMessage())
{
if (LoadString(hInst, IDS_DSTCHANGED, msg, MAX_DSTMSGLEN) &&
LoadString(hInst, IDS_DSTTIMEINFO, title, MAX_DSTTITLELEN))
{
MessageBox(GetForegroundWindow(), msg, title, MB_OK);
}
}
#endif // TASKMANDSTSAMPLE
}
}
break;
default :
{
DEBUGMSG(ZONE_DST, (_T("unexpected value returned from WaitForMultipleObjects")));
DEBUGCHK(0);
}
}
}
/*++
Routine Description:
Determines real date that DST starts based on
systemtime struct returned from GetTimeZoneInfo
Arguments:
pointer to SYSTEMTIME structure
Return Value:
TRUE if successful
--*/
BOOL DST_DetermineChangeDate(LPSYSTEMTIME pst)
{
static BOOL bReEntered = FALSE;
BOOL bRetval = FALSE;
ASSERT(pst);
if (NULL == pst)
return bRetval;
LONGLONG llChangeDate = 0, llNow = 0;
// yes - February can have 29 days, but as of 6/01, no country changes dst in Feb,
// and certainly no one would change on the last day of February
static const int lastDayOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
SYSTEMTIME st;
GetLocalTime(&st);
// build up the new structure
if (pst->wYear == 0)
pst->wYear = st.wYear;
//look for daylight date
switch (pst->wDay)
{
bRetval = TRUE;
case FIRST_OF_MONTH :
{
//Day
pst->wDay = 1; //
int day = DowFromDate(pst);
if (day)
{
pst->wDay = (8 - day) ;
}
//else the first is xxxday - nothing to do since wDay is already 1
break;
}
case LAST_OF_MONTH :
{
//Day
pst->wDay = lastDayOfMonth[pst->wMonth + 1];
int day = DowFromDate(pst);
pst->wDay = (pst->wDay - day) +pst->wDayOfWeek;
break;
}
default :
DEBUGCHK(_T("Unknown DST Format"));
bRetval = FALSE;
}
// Need to determine if the next occurrance of this date is THIS year or NEXT year
VERIFY(SystemTimeToFileTime(pst, (FILETIME *)&llChangeDate));
VERIFY(SystemTimeToFileTime(&st, (FILETIME *)&llNow));
//do we switch after Jan 1?
if (!bReEntered && (llChangeDate < llNow))
{
bReEntered = TRUE;
//need to redetermine the date for next year
pst->wYear++;
DST_DetermineChangeDate(pst);
}
bReEntered = FALSE;
return bRetval;
}
/*++
Routine Description:
Find the day of the week the indicated month begins on
Arguments:
yr year, must be > 0
mo month, number 1-12
Return Value:
day of the week (0-6) on which the month begins
(0 = Sunday, 1 = Monday etc.)
--*/
int GetStartDowForMonth(int yr, int mo)
{
int dow;
// we want monday = 0, sunday = 6
// dow = 6 + (yr - 1) + ((yr - 1) >> 2);
dow = 5 + (yr - 1) + ((yr - 1) >> 2);
if (yr > 1752)
dow += ((yr - 1) - 1600) / 400 - ((yr - 1) - 1700) / 100 - 11;
else if (yr == 1752 && mo > 9)
dow -= 11;
dow += AccumDaysByMonth[mo - 1];
if (mo > 2 && (yr & 03) == 0 && (yr <= 1750 || yr % 100 != 0 || yr % 400 == 0))
dow++;
dow %= 7;
return dow;
}
/*++
Routine Description:
determines the day of week based on information in a SYSTEMTIME struct
Arguments:
pointer to a SYSTEMTIME struct
Return Value:
0 based day of week based on systemtime struct
--*/
int DowFromDate(SYSTEMTIME *pst)
{
int dow;
ASSERT(pst);
dow = GetStartDowForMonth(pst->wYear, pst->wMonth);
dow = (dow + pst->wDay) % 7;
return dow;
}
/*++
Routine Description:
determines if the current locale supports DST based on
information in a TIME_ZONE_INFORMATION struct
Arguments:
pointer to a TIME_ZONE_INFORMATION struct
Return Value:
TRUE if the locale supports DST, FALSE otherwise
--*/
BOOL LocaleSupportsDST(TIME_ZONE_INFORMATION *ptzi)
{
ASSERT(ptzi);
// If the month value is zero then this locale does not change for DST
// it should never be the case that we have a DST date but not a SDT date
ASSERT(((0 != ptzi->StandardDate.wMonth) && (0 != ptzi->DaylightDate.wMonth)) ||
((0 == ptzi->StandardDate.wMonth) && (0 == ptzi->DaylightDate.wMonth)));
if ((0 != ptzi->StandardDate.wMonth) && (0 != ptzi->DaylightDate.wMonth))
return TRUE;
else
return FALSE;
}
#endif //NODSTSAMPLE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -