diff options
author | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-05-15 10:38:20 +0000 |
---|---|---|
committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-05-15 10:38:20 +0000 |
commit | 48540940b6c28bb4378abfeb500ec45a625b37b6 (patch) | |
tree | 2ef294c0763e802f91d868bdef4229b6868527de /src/modules/utils/timeutils.cpp | |
parent | 5c350913f011e119127baeb32a6aedeb4f0d33bc (diff) |
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules/utils/timeutils.cpp')
-rw-r--r-- | src/modules/utils/timeutils.cpp | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/src/modules/utils/timeutils.cpp b/src/modules/utils/timeutils.cpp new file mode 100644 index 0000000000..a0d4c02e46 --- /dev/null +++ b/src/modules/utils/timeutils.cpp @@ -0,0 +1,277 @@ +/*
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2010 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+implements services to handle location - based timezones, instead of
+simple UTC offsets.
+*/
+
+#include "commonheaders.h"
+
+//KB167296
+void UnixTimeToFileTime(time_t ts, LPFILETIME pft)
+{
+ unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64;
+ pft->dwLowDateTime = (DWORD)ll;
+ pft->dwHighDateTime = ll >> 32;
+}
+
+time_t FileTimeToUnixTime(LPFILETIME pft)
+{
+ unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime;
+ ll -= 116444736000000000i64;
+ return (time_t)(ll / 10000000);
+}
+
+void FormatTime(const SYSTEMTIME *st, const TCHAR *szFormat, TCHAR *szDest, int cbDest)
+{
+ if (szDest == NULL || cbDest == 0) return;
+
+ TCHAR *pDest = szDest;
+ int destCharsLeft = cbDest - 1;
+
+ for (const TCHAR* pFormat = szFormat; *pFormat; ++pFormat)
+ {
+ DWORD fmt;
+ bool date, iso = false;
+ switch (*pFormat)
+ {
+ case 't':
+ fmt = TIME_NOSECONDS;
+ date = false;
+ break;
+
+ case 's':
+ fmt = 0;
+ date = false;
+ break;
+
+ case 'm':
+ fmt = TIME_NOMINUTESORSECONDS;
+ date = false;
+ break;
+
+ case 'd':
+ fmt = DATE_SHORTDATE;
+ date = true;
+ break;
+
+ case 'D':
+ fmt = DATE_LONGDATE;
+ date = true;
+ break;
+
+ case 'I':
+ iso = true;
+ break;
+
+ default:
+ if (destCharsLeft--)
+ *pDest++ = *pFormat;
+ continue;
+ }
+
+ TCHAR dateTimeStr[64];
+ int dateTimeStrLen;
+
+ if (iso)
+ {
+ dateTimeStrLen = mir_sntprintf(dateTimeStr, SIZEOF(dateTimeStr),
+ _T("%d-%02d-%02dT%02d:%02d:%02dZ"),
+ st->wYear, st->wMonth, st->wDay,
+ st->wHour, st->wMinute, st->wSecond) + 1;
+ }
+ else if (date)
+ dateTimeStrLen = GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, NULL,
+ dateTimeStr, SIZEOF(dateTimeStr));
+ else
+ dateTimeStrLen = GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, NULL,
+ dateTimeStr, SIZEOF(dateTimeStr));
+
+ if (dateTimeStrLen) --dateTimeStrLen;
+ if (destCharsLeft < dateTimeStrLen) dateTimeStrLen = destCharsLeft;
+ memcpy(pDest, dateTimeStr, dateTimeStrLen * sizeof(dateTimeStr[0]));
+ destCharsLeft -= dateTimeStrLen;
+ pDest += dateTimeStrLen;
+ }
+ *pDest = 0;
+}
+
+
+#ifndef _UNICODE
+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(LPTIME_ZONE_INFORMATION ptzi, LPSYSTEMTIME pstUtc, LPSYSTEMTIME pstLoc)
+{
+ // st is UTC
+
+ FILETIME ft ;
+ LARGE_INTEGER li ;
+ SYSTEMTIME stDst ;
+
+ if (IsWinVerNT())
+ return SystemTimeToTzSpecificLocalTime(ptzi, 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 ;
+}
+#endif
|