Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentimezone.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
1.7.6.1
|