ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

timezone.c
Go to the documentation of this file.
00001 /* $Id: timezone.c 52819 2011-07-23 18:54:29Z ion $
00002  *
00003  * COPYRIGHT:       See COPYING in the top level directory
00004  * PROJECT:         ReactOS system libraries
00005  * FILE:            lib/kernel32/misc/time.c
00006  * PURPOSE:         Time conversion functions
00007  * PROGRAMMER:      Ariadne
00008  *                  DOSDATE and DOSTIME structures from Onno Hovers
00009  * UPDATE HISTORY:
00010  *                  Created 19/01/99
00011  */
00012 
00013 /* INCLUDES ******************************************************************/
00014 
00015 #include <k32.h>
00016 
00017 #define NDEBUG
00018 #include <debug.h>
00019 
00020 /* TYPES *********************************************************************/
00021 
00022 #define TICKSPERMIN 600000000
00023 
00024 #define LL2FILETIME( ll, pft )\
00025     (pft)->dwLowDateTime = (UINT)(ll); \
00026     (pft)->dwHighDateTime = (UINT)((ll) >> 32);
00027 #define FILETIME2LL( pft, ll) \
00028     ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ;
00029 
00030 static const int MonthLengths[2][12] =
00031 {
00032     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00033     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00034 };
00035 
00036 /* STATIC FUNTIONS **********************************************************/
00037 
00038 static inline int IsLeapYear(int Year)
00039 {
00040     return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
00041 }
00042 
00043 /***********************************************************************
00044  *  TIME_DayLightCompareDate
00045  *
00046  * Compares two dates without looking at the year.
00047  *
00048  * PARAMS
00049  *   date        [in] The local time to compare.
00050  *   compareDate [in] The daylight savings begin or end date.
00051  *
00052  * RETURNS
00053  *
00054  *  -1 if date < compareDate
00055  *   0 if date == compareDate
00056  *   1 if date > compareDate
00057  *  -2 if an error occurs
00058  */
00059 static int
00060 TIME_DayLightCompareDate(const SYSTEMTIME *date, const SYSTEMTIME *compareDate)
00061 {
00062     int limit_day, dayinsecs;
00063 
00064     if (date->wMonth < compareDate->wMonth)
00065         return -1; /* We are in a month before the date limit. */
00066 
00067     if (date->wMonth > compareDate->wMonth)
00068         return 1; /* We are in a month after the date limit. */
00069 
00070     /* if year is 0 then date is in day-of-week format, otherwise
00071      * it's absolute date.
00072      */
00073     if (compareDate->wYear == 0)
00074     {
00075         WORD First;
00076         /* compareDate->wDay is interpreted as number of the week in the month
00077          * 5 means: the last week in the month */
00078         int weekofmonth = compareDate->wDay;
00079           /* calculate the day of the first DayOfWeek in the month */
00080         First = ( 6 + compareDate->wDayOfWeek - date->wDayOfWeek + date->wDay 
00081                ) % 7 + 1;
00082         limit_day = First + 7 * (weekofmonth - 1);
00083         /* check needed for the 5th weekday of the month */
00084         if(limit_day > MonthLengths[date->wMonth==2 && IsLeapYear(date->wYear)]
00085                 [date->wMonth - 1])
00086             limit_day -= 7;
00087     }
00088     else
00089     {
00090        limit_day = compareDate->wDay;
00091     }
00092 
00093     /* convert to seconds */
00094     limit_day = ((limit_day * 24  + compareDate->wHour) * 60 +
00095             compareDate->wMinute ) * 60;
00096     dayinsecs = ((date->wDay * 24  + date->wHour) * 60 +
00097             date->wMinute ) * 60 + date->wSecond;
00098     /* and compare */
00099     return dayinsecs < limit_day ? -1 :
00100            dayinsecs > limit_day ? 1 :
00101            0;   /* date is equal to the date limit. */
00102 }
00103 
00104 /***********************************************************************
00105  *  TIME_CompTimeZoneID
00106  *
00107  *  Computes the local time bias for a given time and time zone.
00108  *
00109  *  PARAMS
00110  *      pTZinfo     [in] The time zone data.
00111  *      lpFileTime  [in] The system or local time.
00112  *      islocal     [in] it is local time.
00113  *
00114  *  RETURNS
00115  *      TIME_ZONE_ID_INVALID    An error occurred
00116  *      TIME_ZONE_ID_UNKNOWN    There are no transition time known
00117  *      TIME_ZONE_ID_STANDARD   Current time is standard time
00118  *      TIME_ZONE_ID_DAYLIGHT   Current time is daylight savings time
00119  */
00120 static
00121 DWORD
00122 TIME_CompTimeZoneID( const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal )
00123 {
00124     int ret;
00125     BOOL beforeStandardDate, afterDaylightDate;
00126     DWORD retval = TIME_ZONE_ID_INVALID;
00127     LONGLONG llTime = 0; /* initialized to prevent gcc complaining */
00128     SYSTEMTIME SysTime;
00129     FILETIME ftTemp;
00130 
00131     if (pTZinfo->DaylightDate.wMonth != 0)
00132     {
00133         /* if year is 0 then date is in day-of-week format, otherwise
00134          * it's absolute date.
00135          */
00136         if (pTZinfo->StandardDate.wMonth == 0 ||
00137             (pTZinfo->StandardDate.wYear == 0 &&
00138             (pTZinfo->StandardDate.wDay<1 ||
00139             pTZinfo->StandardDate.wDay>5 ||
00140             pTZinfo->DaylightDate.wDay<1 ||
00141             pTZinfo->DaylightDate.wDay>5)))
00142         {
00143             SetLastError(ERROR_INVALID_PARAMETER);
00144             return TIME_ZONE_ID_INVALID;
00145         }
00146 
00147         if (!islocal) {
00148             FILETIME2LL( lpFileTime, llTime );
00149             llTime -= ( pTZinfo->Bias + pTZinfo->DaylightBias )
00150                 * (LONGLONG)TICKSPERMIN;
00151             LL2FILETIME( llTime, &ftTemp)
00152             lpFileTime = &ftTemp;
00153         }
00154 
00155         FileTimeToSystemTime(lpFileTime, &SysTime);
00156         
00157          /* check for daylight savings */
00158         ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate);
00159         if (ret == -2)
00160           return TIME_ZONE_ID_INVALID;
00161 
00162         beforeStandardDate = ret < 0;
00163 
00164         if (!islocal) {
00165             llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias )
00166                 * (LONGLONG)TICKSPERMIN;
00167             LL2FILETIME( llTime, &ftTemp)
00168             FileTimeToSystemTime(lpFileTime, &SysTime);
00169         }
00170 
00171         ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate);
00172         if (ret == -2)
00173           return TIME_ZONE_ID_INVALID;
00174 
00175         afterDaylightDate = ret >= 0;
00176 
00177         retval = TIME_ZONE_ID_STANDARD;
00178         if( pTZinfo->DaylightDate.wMonth <  pTZinfo->StandardDate.wMonth ) {
00179             /* Northern hemisphere */
00180             if( beforeStandardDate && afterDaylightDate )
00181                 retval = TIME_ZONE_ID_DAYLIGHT;
00182         } else    /* Down south */
00183             if( beforeStandardDate || afterDaylightDate )
00184             retval = TIME_ZONE_ID_DAYLIGHT;
00185     } else 
00186         /* No transition date */
00187         retval = TIME_ZONE_ID_UNKNOWN;
00188         
00189     return retval;
00190 }
00191 
00192 /***********************************************************************
00193  *  TIME_TimeZoneID
00194  *
00195  *  Calculates whether daylight savings is on now.
00196  *
00197  *  PARAMS
00198  *      pTzi [in] Timezone info.
00199  *
00200  *  RETURNS
00201  *      TIME_ZONE_ID_INVALID    An error occurred
00202  *      TIME_ZONE_ID_UNKNOWN    There are no transition time known
00203  *      TIME_ZONE_ID_STANDARD   Current time is standard time
00204  *      TIME_ZONE_ID_DAYLIGHT   Current time is daylight savings time
00205  */
00206 static DWORD TIME_ZoneID( const TIME_ZONE_INFORMATION *pTzi )
00207 {
00208     FILETIME ftTime;
00209     GetSystemTimeAsFileTime( &ftTime);
00210     return TIME_CompTimeZoneID( pTzi, &ftTime, FALSE);
00211 }
00212 
00213 /***********************************************************************
00214  *  TIME_GetTimezoneBias
00215  *
00216  *  Calculates the local time bias for a given time zone.
00217  *
00218  * PARAMS
00219  *  pTZinfo    [in]  The time zone data.
00220  *  lpFileTime [in]  The system or local time.
00221  *  islocal    [in]  It is local time.
00222  *  pBias      [out] The calculated bias in minutes.
00223  *
00224  * RETURNS
00225  *  TRUE when the time zone bias was calculated.
00226  */
00227 static BOOL
00228 TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal, LONG *pBias)
00229 {
00230     LONG bias = pTZinfo->Bias;
00231     DWORD tzid = TIME_CompTimeZoneID(pTZinfo, lpFileTime, islocal);
00232 
00233     if( tzid == TIME_ZONE_ID_INVALID)
00234         return FALSE;
00235     if (tzid == TIME_ZONE_ID_DAYLIGHT)
00236         bias += pTZinfo->DaylightBias;
00237     else if (tzid == TIME_ZONE_ID_STANDARD)
00238         bias += pTZinfo->StandardBias;
00239     *pBias = bias;
00240     return TRUE;
00241 }
00242 
00243 
00244 /* FUNCTIONS ****************************************************************/
00245 
00246 /*
00247  * @implemented
00248  */
00249 DWORD
00250 WINAPI
00251 GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
00252 {
00253     NTSTATUS Status;
00254 
00255     DPRINT("GetTimeZoneInformation()\n");
00256 
00257     Status = NtQuerySystemInformation(SystemCurrentTimeZoneInformation,
00258                                       lpTimeZoneInformation,
00259                                       sizeof(TIME_ZONE_INFORMATION),
00260                                       NULL);
00261     if (!NT_SUCCESS(Status))
00262     {
00263         BaseSetLastNTError(Status);
00264         return TIME_ZONE_ID_INVALID;
00265     }
00266 
00267     return TIME_ZoneID(lpTimeZoneInformation);
00268 }
00269 
00270 
00271 /*
00272  * @implemented
00273  */
00274 BOOL
00275 WINAPI
00276 SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation)
00277 {
00278     NTSTATUS Status;
00279 
00280     DPRINT("SetTimeZoneInformation()\n");
00281 
00282     Status = RtlSetTimeZoneInformation((LPTIME_ZONE_INFORMATION)lpTimeZoneInformation);
00283     if (!NT_SUCCESS(Status))
00284     {
00285         DPRINT1("RtlSetTimeZoneInformation() failed (Status %lx)\n", Status);
00286         BaseSetLastNTError(Status);
00287         return FALSE;
00288     }
00289 
00290     Status = NtSetSystemInformation(SystemCurrentTimeZoneInformation,
00291                                     (PVOID)lpTimeZoneInformation,
00292                                     sizeof(TIME_ZONE_INFORMATION));
00293     if (!NT_SUCCESS(Status))
00294     {
00295         DPRINT1("NtSetSystemInformation() failed (Status %lx)\n", Status);
00296         BaseSetLastNTError(Status);
00297         return FALSE;
00298     }
00299 
00300     return TRUE;
00301 }
00302 
00303 /*
00304  * @implemented
00305  */
00306 BOOL
00307 WINAPI
00308 SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation,
00309                                 CONST SYSTEMTIME *lpUniversalTime,
00310                                 LPSYSTEMTIME lpLocalTime)
00311 {
00312     TIME_ZONE_INFORMATION TzInfo;
00313     FILETIME FileTime;
00314     LONGLONG llTime;
00315     LONG lBias;
00316 
00317     if (lpTimeZoneInformation != NULL)
00318     {
00319         TzInfo = *lpTimeZoneInformation;
00320     }
00321     else
00322     {
00323         if (GetTimeZoneInformation(&TzInfo) == TIME_ZONE_ID_INVALID)
00324             return FALSE;
00325     }
00326 
00327     if (!lpUniversalTime || !lpLocalTime)
00328         return FALSE;
00329 
00330     if (!SystemTimeToFileTime(lpUniversalTime, &FileTime))
00331         return FALSE;
00332 
00333     FILETIME2LL(&FileTime, llTime)
00334 
00335     if (!TIME_GetTimezoneBias(&TzInfo, &FileTime, FALSE, &lBias))
00336         return FALSE;
00337 
00338     /* convert minutes to 100-nanoseconds-ticks */
00339     llTime -= (LONGLONG)lBias * TICKSPERMIN;
00340 
00341     LL2FILETIME( llTime, &FileTime)
00342 
00343     return FileTimeToSystemTime(&FileTime, lpLocalTime);
00344 }
00345 
00346 
00347 /*
00348  * @implemented (Wine 13 sep 2008)
00349  */
00350 BOOL
00351 WINAPI
00352 TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation,
00353                                 LPSYSTEMTIME lpLocalTime,
00354                                 LPSYSTEMTIME lpUniversalTime)
00355 {
00356     FILETIME ft;
00357     LONG lBias;
00358     LONGLONG t;
00359     TIME_ZONE_INFORMATION tzinfo;
00360 
00361     if (lpTimeZoneInformation != NULL)
00362     {
00363         tzinfo = *lpTimeZoneInformation;
00364     }
00365     else
00366     {
00367         if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID)
00368             return FALSE;
00369     }
00370 
00371     if (!SystemTimeToFileTime(lpLocalTime, &ft))
00372         return FALSE;
00373     FILETIME2LL( &ft, t)
00374     if (!TIME_GetTimezoneBias(&tzinfo, &ft, TRUE, &lBias))
00375         return FALSE;
00376     /* convert minutes to 100-nanoseconds-ticks */
00377     t += (LONGLONG)lBias * TICKSPERMIN;
00378     LL2FILETIME( t, &ft)
00379     return FileTimeToSystemTime(&ft, lpUniversalTime);
00380 }
00381 
00382 /* EOF */

Generated on Sat May 26 2012 04:19:48 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.