diff options
Diffstat (limited to 'worldtime/time_convert.cpp')
-rw-r--r-- | worldtime/time_convert.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/worldtime/time_convert.cpp b/worldtime/time_convert.cpp new file mode 100644 index 0000000..bfd2781 --- /dev/null +++ b/worldtime/time_convert.cpp @@ -0,0 +1,209 @@ +#include "common.h"
+#include "time_convert.h"
+
+void ConvertToAbsolute (const SYSTEMTIME * pstLoc, const SYSTEMTIME * pstDst, SYSTEMTIME * pstDstAbs)
+{
+ static int iDays [12] = { 31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31 } ;
+ int iDay ;
+
+ // Set up the aboluste date structure except for wDay, which we must find
+
+ pstDstAbs->wYear = pstLoc->wYear ; // Notice from local date/time
+ pstDstAbs->wMonth = pstDst->wMonth ;
+ pstDstAbs->wDayOfWeek = pstDst->wDayOfWeek ;
+
+ pstDstAbs->wHour = pstDst->wHour ;
+ pstDstAbs->wMinute = pstDst->wMinute ;
+ pstDstAbs->wSecond = pstDst->wSecond ;
+ pstDstAbs->wMilliseconds = pstDst->wMilliseconds ;
+
+ // Fix the iDays array for leap years
+
+ if ((pstLoc->wYear % 4 == 0) && ((pstLoc->wYear % 100 != 0) ||
+ (pstLoc->wYear % 400 == 0)))
+ {
+ iDays[1] = 29 ;
+ }
+
+ // Find a day of the month that falls on the same
+ // day of the week as the transition.
+
+ // Suppose today is the 20th of the month (pstLoc->wDay = 20)
+ // Suppose today is a Wednesday (pstLoc->wDayOfWeek = 3)
+ // Suppose the transition occurs on a Friday (pstDst->wDayOfWeek = 5)
+ // Then iDay = 31, meaning that the 31st falls on a Friday
+ // (The 7 is this formula avoids negatives.)
+
+ iDay = pstLoc->wDay + pstDst->wDayOfWeek + 7 - pstLoc->wDayOfWeek ;
+
+ // Now shrink iDay to a value between 1 and 7.
+
+ iDay = (iDay - 1) % 7 + 1 ;
+
+ // Now iDay is a day of the month ranging from 1 to 7.
+ // Recall that the wDay field of the structure can range
+ // from 1 to 5, 1 meaning "first", 2 meaning "second",
+ // and 5 meaning "last".
+ // So, increase iDay so it's the proper day of the month.
+
+ iDay += 7 * (pstDst->wDay - 1) ;
+
+ // Could be that iDay overshot the end of the month, so
+ // fix it up using the number of days in each month
+
+ if (iDay > iDays[pstDst->wMonth - 1])
+ iDay -= 7 ;
+
+ // Assign that day to the structure.
+
+ pstDstAbs->wDay = iDay ;
+}
+
+BOOL LocalGreaterThanTransition (const SYSTEMTIME * pstLoc, const SYSTEMTIME * pstTran)
+{
+ FILETIME ftLoc, ftTran ;
+ LARGE_INTEGER liLoc, liTran ;
+ SYSTEMTIME stTranAbs ;
+
+ // Easy case: Just compare the two months
+
+ if (pstLoc->wMonth != pstTran->wMonth)
+ return (pstLoc->wMonth > pstTran->wMonth) ;
+
+ // Well, we're in a transition month. That requires a bit more work.
+
+ // Check if pstDst is in absolute or day-in-month format.
+ // (See documentation of TIME_ZONE_INFORMATION, StandardDate field.)
+
+ if (pstTran->wYear) // absolute format (haven't seen one yet!)
+ {
+ stTranAbs = * pstTran ;
+ }
+ else // day-in-month format
+ {
+ ConvertToAbsolute (pstLoc, pstTran, &stTranAbs) ;
+ }
+
+ // Now convert both date/time structures to large integers & compare
+
+ SystemTimeToFileTime (pstLoc, &ftLoc) ;
+ liLoc = * (LARGE_INTEGER *) (void *) &ftLoc ;
+
+ SystemTimeToFileTime (&stTranAbs, &ftTran) ;
+ liTran = * (LARGE_INTEGER *) (void *) &ftTran ;
+
+ return (liLoc.QuadPart > liTran.QuadPart) ;
+}
+
+BOOL MySystemTimeToTzSpecificLocalTime(const TIME_ZONE_INFORMATION *ptzi, const SYSTEMTIME *pstUtc, SYSTEMTIME *pstLoc) {
+ // st is UTC
+
+ FILETIME ft ;
+ LARGE_INTEGER li ;
+ SYSTEMTIME stDst ;
+
+ // If we're running under NT, just call the real function
+
+ if (!(0x80000000 & GetVersion()))
+ return SystemTimeToTzSpecificLocalTime ((TIME_ZONE_INFORMATION *) ptzi, (SYSTEMTIME *) pstUtc, pstLoc) ;
+
+ // Convert time to a LARGE_INTEGER and subtract the bias
+
+ SystemTimeToFileTime (pstUtc, &ft) ;
+ li = * (LARGE_INTEGER *) (void *) &ft;
+ li.QuadPart -= (LONGLONG) 600000000 * ptzi->Bias ;
+
+ // Convert to a local date/time before application of daylight saving time.
+ // The local date/time must be used to determine when the conversion occurs.
+
+ ft = * (FILETIME *) (void *) &li ;
+ FileTimeToSystemTime (&ft, pstLoc) ;
+
+ // Find the time assuming Daylight Saving Time
+
+ li.QuadPart -= (LONGLONG) 600000000 * ptzi->DaylightBias ;
+ ft = * (FILETIME *) (void *) &li ;
+ FileTimeToSystemTime (&ft, &stDst) ;
+
+ // Now put li back the way it was
+
+ li.QuadPart += (LONGLONG) 600000000 * ptzi->DaylightBias ;
+
+ if (ptzi->StandardDate.wMonth) // ie, daylight savings time
+ {
+ // Northern hemisphere
+
+ if ((ptzi->DaylightDate.wMonth < ptzi->StandardDate.wMonth) &&
+
+ (stDst.wMonth >= pstLoc->wMonth) && // avoid the end of year problem
+
+ LocalGreaterThanTransition (pstLoc, &ptzi->DaylightDate) &&
+ !LocalGreaterThanTransition (&stDst, &ptzi->StandardDate))
+ {
+ li.QuadPart -= (LONGLONG) 600000000 * ptzi->DaylightBias ;
+ }
+ // Southern hemisphere
+
+ else if ((ptzi->StandardDate.wMonth < ptzi->DaylightDate.wMonth) &&
+ (!LocalGreaterThanTransition (&stDst, &ptzi->StandardDate) ||
+ LocalGreaterThanTransition (pstLoc, &ptzi->DaylightDate)))
+ {
+ li.QuadPart -= (LONGLONG) 600000000 * ptzi->DaylightBias ;
+ }
+ else
+ {
+ li.QuadPart -= (LONGLONG) 600000000 * ptzi->StandardBias ;
+ }
+ }
+
+ ft = * (FILETIME *) (void *) &li ;
+ FileTimeToSystemTime (&ft, pstLoc) ;
+ return TRUE ;
+}
+
+VOID MyGetSystemTime(LPSYSTEMTIME lpSystemTime) {
+ //TIME_ZONE_INFORMATION tzi;
+ //FILETIME ft;
+ //LARGE_INTEGER li;
+
+ GetSystemTime(lpSystemTime);
+ //GetTimeZoneInformation(&tzi);
+
+ /*
+ // the following corrects for the condition that occurs when 'automatically adjust for daylight savings' is off, but
+ // local timezone info says it is daylight savings time...
+ // it assumes that the timezone has not been adjusted but the time has instead - resulting in wrong GMT in the system clock
+
+ if(tzi.StandardDate.wMonth != 0 && tzi.DaylightBias == 0 && tzi.StandardBias == 0) {
+ // Northern hemisphere
+ if ((tzi.DaylightDate.wMonth < tzi.StandardDate.wMonth) &&
+
+ LocalGreaterThanTransition (lpSystemTime, &tzi.DaylightDate) &&
+ !LocalGreaterThanTransition (lpSystemTime, &tzi.StandardDate))
+ {
+ // add one hour to the system time
+ SystemTimeToFileTime(lpSystemTime, &ft);
+ li = * (LARGE_INTEGER *) (void *) &ft;
+ li.QuadPart += (LONGLONG) 600000000 * 60;
+ ft = * (FILETIME *) (void *) &li ;
+ FileTimeToSystemTime(&ft, lpSystemTime);
+ }
+ // Southern hemisphere
+
+ else if ((tzi.StandardDate.wMonth < tzi.DaylightDate.wMonth) &&
+ (!LocalGreaterThanTransition (lpSystemTime, &tzi.StandardDate) ||
+ LocalGreaterThanTransition (lpSystemTime, &tzi.DaylightDate)))
+ {
+ // add one hour to the system time
+ SystemTimeToFileTime(lpSystemTime, &ft);
+ li = * (LARGE_INTEGER *) (void *) &ft;
+ li.QuadPart += (LONGLONG) 600000000 * 60;
+ ft = * (FILETIME *) (void *) &li ;
+ FileTimeToSystemTime(&ft, lpSystemTime);
+ }
+
+ }
+ */
+}
+
|