1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_tools.hxx" 26 27 #define _TOOLS_TIME_CXX 28 29 #if defined( OS2 ) 30 #define INCL_DOSMISC 31 #define INCL_DOSDATETIME 32 #include <svpm.h> 33 #elif defined( WNT ) 34 #ifdef _MSC_VER 35 #pragma warning (push,1) 36 #endif 37 #include <tools/svwin.h> 38 #ifdef _MSC_VER 39 #pragma warning (pop) 40 #endif 41 #elif defined UNX 42 #include <unistd.h> 43 #include <limits.h> 44 #include <math.h> 45 #include <sys/time.h> 46 #endif 47 48 #include <time.h> 49 #include <tools/time.hxx> 50 51 #if defined(SOLARIS) && defined(__GNUC__) 52 extern long altzone; 53 #endif 54 55 // ======================================================================= 56 57 static sal_Int32 TimeToSec100( const Time& rTime ) 58 { 59 short nSign = (rTime.GetTime() >= 0) ? +1 : -1; 60 sal_Int32 nHour = rTime.GetHour(); 61 sal_Int32 nMin = rTime.GetMin(); 62 sal_Int32 nSec = rTime.GetSec(); 63 sal_Int32 n100Sec = rTime.Get100Sec(); 64 65 // Wegen Interal Compiler Error bei MSC, etwas komplizierter 66 // return (n100Sec + (nSec*100) + (nMin*60*100) + (nHour*60*60*100) * nSign); 67 68 sal_Int32 nRet = n100Sec; 69 nRet += nSec*100; 70 nRet += nMin*60*100; 71 nRet += nHour*60*60*100; 72 73 return (nRet * nSign); 74 } 75 76 // ----------------------------------------------------------------------- 77 78 static Time Sec100ToTime( sal_Int32 nSec100 ) 79 { 80 short nSign; 81 if ( nSec100 < 0 ) 82 { 83 nSec100 *= -1; 84 nSign = -1; 85 } 86 else 87 nSign = 1; 88 89 Time aTime( 0, 0, 0, nSec100 ); 90 aTime.SetTime( aTime.GetTime() * nSign ); 91 return aTime; 92 } 93 94 // ======================================================================= 95 96 Time::Time() 97 { 98 #if defined( OS2 ) 99 DATETIME aDateTime; 100 DosGetDateTime( &aDateTime ); 101 102 // Zeit zusammenbauen 103 nTime = (((sal_Int32)aDateTime.hours)*1000000) + 104 (((sal_Int32)aDateTime.minutes)*10000) + 105 (((sal_Int32)aDateTime.seconds)*100) + 106 ((sal_Int32)aDateTime.hundredths); 107 #elif defined( WNT ) 108 SYSTEMTIME aDateTime; 109 GetLocalTime( &aDateTime ); 110 111 // Zeit zusammenbauen 112 nTime = (((sal_Int32)aDateTime.wHour)*1000000) + 113 (((sal_Int32)aDateTime.wMinute)*10000) + 114 (((sal_Int32)aDateTime.wSecond)*100) + 115 ((sal_Int32)aDateTime.wMilliseconds/10); 116 #else 117 time_t nTmpTime; 118 struct tm aTime; 119 120 // Zeit ermitteln 121 nTmpTime = time( 0 ); 122 123 // Zeit zusammenbauen 124 if ( localtime_r( &nTmpTime, &aTime ) ) 125 { 126 nTime = (((sal_Int32)aTime.tm_hour)*1000000) + 127 (((sal_Int32)aTime.tm_min)*10000) + 128 (((sal_Int32)aTime.tm_sec)*100); 129 } 130 else 131 nTime = 0; 132 #endif 133 } 134 135 // ----------------------------------------------------------------------- 136 137 Time::Time( const Time& rTime ) 138 { 139 nTime = rTime.nTime; 140 } 141 142 // ----------------------------------------------------------------------- 143 144 Time::Time( sal_uIntPtr nHour, sal_uIntPtr nMin, sal_uIntPtr nSec, sal_uIntPtr n100Sec ) 145 { 146 // Zeit normalisieren 147 nSec += n100Sec / 100; 148 n100Sec = n100Sec % 100; 149 nMin += nSec / 60; 150 nSec = nSec % 60; 151 nHour += nMin / 60; 152 nMin = nMin % 60; 153 154 // Zeit zusammenbauen 155 nTime = (sal_Int32)(n100Sec + (nSec*100) + (nMin*10000) + (nHour*1000000)); 156 } 157 158 // ----------------------------------------------------------------------- 159 160 void Time::SetHour( sal_uInt16 nNewHour ) 161 { 162 short nSign = (nTime >= 0) ? +1 : -1; 163 sal_Int32 nMin = GetMin(); 164 sal_Int32 nSec = GetSec(); 165 sal_Int32 n100Sec = Get100Sec(); 166 167 nTime = (n100Sec + (nSec*100) + (nMin*10000) + 168 (((sal_Int32)nNewHour)*1000000)) * nSign; 169 } 170 171 // ----------------------------------------------------------------------- 172 173 void Time::SetMin( sal_uInt16 nNewMin ) 174 { 175 short nSign = (nTime >= 0) ? +1 : -1; 176 sal_Int32 nHour = GetHour(); 177 sal_Int32 nSec = GetSec(); 178 sal_Int32 n100Sec = Get100Sec(); 179 180 // kein Ueberlauf 181 nNewMin = nNewMin % 60; 182 183 nTime = (n100Sec + (nSec*100) + (((sal_Int32)nNewMin)*10000) + 184 (nHour*1000000)) * nSign; 185 } 186 187 // ----------------------------------------------------------------------- 188 189 void Time::SetSec( sal_uInt16 nNewSec ) 190 { 191 short nSign = (nTime >= 0) ? +1 : -1; 192 sal_Int32 nHour = GetHour(); 193 sal_Int32 nMin = GetMin(); 194 sal_Int32 n100Sec = Get100Sec(); 195 196 // kein Ueberlauf 197 nNewSec = nNewSec % 60; 198 199 nTime = (n100Sec + (((sal_Int32)nNewSec)*100) + (nMin*10000) + 200 (nHour*1000000)) * nSign; 201 } 202 203 // ----------------------------------------------------------------------- 204 205 void Time::Set100Sec( sal_uInt16 nNew100Sec ) 206 { 207 short nSign = (nTime >= 0) ? +1 : -1; 208 sal_Int32 nHour = GetHour(); 209 sal_Int32 nMin = GetMin(); 210 sal_Int32 nSec = GetSec(); 211 212 // kein Ueberlauf 213 nNew100Sec = nNew100Sec % 100; 214 215 nTime = (((sal_Int32)nNew100Sec) + (nSec*100) + (nMin*10000) + 216 (nHour*1000000)) * nSign; 217 } 218 219 // ----------------------------------------------------------------------- 220 221 sal_Int32 Time::GetMSFromTime() const 222 { 223 short nSign = (nTime >= 0) ? +1 : -1; 224 sal_Int32 nHour = GetHour(); 225 sal_Int32 nMin = GetMin(); 226 sal_Int32 nSec = GetSec(); 227 sal_Int32 n100Sec = Get100Sec(); 228 229 return (((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10))*nSign); 230 } 231 232 // ----------------------------------------------------------------------- 233 234 void Time::MakeTimeFromMS( sal_Int32 nMS ) 235 { 236 short nSign; 237 if ( nMS < 0 ) 238 { 239 nMS *= -1; 240 nSign = -1; 241 } 242 else 243 nSign = 1; 244 245 Time aTime( 0, 0, 0, nMS/10 ); 246 SetTime( aTime.GetTime() * nSign ); 247 } 248 249 // ----------------------------------------------------------------------- 250 251 double Time::GetTimeInDays() const 252 { 253 short nSign = (nTime >= 0) ? +1 : -1; 254 double nHour = GetHour(); 255 double nMin = GetMin(); 256 double nSec = GetSec(); 257 double n100Sec = Get100Sec(); 258 259 return (nHour+(nMin/60)+(nSec/(60*60))+(n100Sec/(60*60*100))) / 24 * nSign; 260 } 261 262 // ----------------------------------------------------------------------- 263 264 Time& Time::operator =( const Time& rTime ) 265 { 266 nTime = rTime.nTime; 267 return *this; 268 } 269 270 // ----------------------------------------------------------------------- 271 272 Time& Time::operator +=( const Time& rTime ) 273 { 274 nTime = Sec100ToTime( TimeToSec100( *this ) + 275 TimeToSec100( rTime ) ).GetTime(); 276 return *this; 277 } 278 279 // ----------------------------------------------------------------------- 280 281 Time& Time::operator -=( const Time& rTime ) 282 { 283 nTime = Sec100ToTime( TimeToSec100( *this ) - 284 TimeToSec100( rTime ) ).GetTime(); 285 return *this; 286 } 287 288 // ----------------------------------------------------------------------- 289 290 Time operator +( const Time& rTime1, const Time& rTime2 ) 291 { 292 return Sec100ToTime( TimeToSec100( rTime1 ) + 293 TimeToSec100( rTime2 ) ); 294 } 295 296 // ----------------------------------------------------------------------- 297 298 Time operator -( const Time& rTime1, const Time& rTime2 ) 299 { 300 return Sec100ToTime( TimeToSec100( rTime1 ) - 301 TimeToSec100( rTime2 ) ); 302 } 303 304 // ----------------------------------------------------------------------- 305 306 sal_Bool Time::IsEqualIgnore100Sec( const Time& rTime ) const 307 { 308 sal_Int32 n1 = (nTime < 0 ? -Get100Sec() : Get100Sec() ); 309 sal_Int32 n2 = (rTime.nTime < 0 ? -rTime.Get100Sec() : rTime.Get100Sec() ); 310 return (nTime - n1) == (rTime.nTime - n2); 311 } 312 313 // ----------------------------------------------------------------------- 314 315 Time Time::GetUTCOffset() 316 { 317 #if defined( OS2 ) 318 #undef timezone 319 DATETIME aDateTime; 320 DosGetDateTime( &aDateTime ); 321 322 // Zeit zusammenbauen 323 if ( aDateTime.timezone != -1 ) 324 { 325 short nTempTime = (short)Abs( aDateTime.timezone ); 326 Time aTime( 0, (sal_uInt16)nTempTime ); 327 if ( aDateTime.timezone > 0 ) 328 aTime = -aTime; 329 return aTime; 330 } 331 else 332 return Time( 0 ); 333 #elif defined( WNT ) 334 TIME_ZONE_INFORMATION aTimeZone; 335 aTimeZone.Bias = 0; 336 DWORD nTimeZoneRet = GetTimeZoneInformation( &aTimeZone ); 337 sal_Int32 nTempTime = aTimeZone.Bias; 338 if ( nTimeZoneRet == TIME_ZONE_ID_STANDARD ) 339 nTempTime += aTimeZone.StandardBias; 340 else if ( nTimeZoneRet == TIME_ZONE_ID_DAYLIGHT ) 341 nTempTime += aTimeZone.DaylightBias; 342 Time aTime( 0, (sal_uInt16)Abs( nTempTime ) ); 343 if ( nTempTime > 0 ) 344 aTime = -aTime; 345 return aTime; 346 #else 347 static sal_uIntPtr nCacheTicks = 0; 348 static sal_Int32 nCacheSecOffset = -1; 349 sal_uIntPtr nTicks = Time::GetSystemTicks(); 350 time_t nTime; 351 tm aTM; 352 sal_Int32 nLocalTime; 353 sal_Int32 nUTC; 354 short nTempTime; 355 356 // Evt. Wert neu ermitteln 357 if ( (nCacheSecOffset == -1) || 358 ((nTicks - nCacheTicks) > 360000) || 359 ( nTicks < nCacheTicks ) // handle overflow 360 ) 361 { 362 nTime = time( 0 ); 363 localtime_r( &nTime, &aTM ); 364 nLocalTime = mktime( &aTM ); 365 #if defined( SOLARIS ) 366 // Solaris gmtime_r() seems not to handle daylight saving time 367 // flags correctly 368 nUTC = nLocalTime + ( aTM.tm_isdst == 0 ? timezone : altzone ); 369 #elif defined( LINUX ) 370 // Linux mktime() seems not to handle tm_isdst correctly 371 nUTC = nLocalTime - aTM.tm_gmtoff; 372 #else 373 gmtime_r( &nTime, &aTM ); 374 nUTC = mktime( &aTM ); 375 #endif 376 nCacheTicks = nTicks; 377 nCacheSecOffset = (nLocalTime-nUTC) / 60; 378 } 379 380 nTempTime = (short)Abs( nCacheSecOffset ); 381 Time aTime( 0, (sal_uInt16)nTempTime ); 382 if ( nCacheSecOffset < 0 ) 383 aTime = -aTime; 384 return aTime; 385 #endif 386 } 387 388 389 // ----------------------------------------------------------------------- 390 391 sal_uIntPtr Time::GetSystemTicks() 392 { 393 #if defined WNT 394 return (sal_uIntPtr)GetTickCount(); 395 #elif defined( OS2 ) 396 sal_uIntPtr nClock; 397 DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) ); 398 return (sal_uIntPtr)nClock; 399 #else 400 timeval tv; 401 gettimeofday (&tv, 0); 402 403 double fTicks = tv.tv_sec; 404 fTicks *= 1000; 405 fTicks += ((tv.tv_usec + 500) / 1000); 406 407 fTicks = fmod (fTicks, double(ULONG_MAX)); 408 return sal_uIntPtr(fTicks); 409 #endif 410 } 411 412 // ----------------------------------------------------------------------- 413 414 sal_uIntPtr Time::GetProcessTicks() 415 { 416 #if defined WNT 417 return (sal_uIntPtr)GetTickCount(); 418 #elif defined( OS2 ) 419 sal_uIntPtr nClock; 420 DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) ); 421 return (sal_uIntPtr)nClock; 422 #else 423 static sal_uIntPtr nImplTicksPerSecond = 0; 424 static double dImplTicksPerSecond; 425 static double dImplTicksULONGMAX; 426 sal_uIntPtr nTicks = (sal_uIntPtr)clock(); 427 428 if ( !nImplTicksPerSecond ) 429 { 430 nImplTicksPerSecond = CLOCKS_PER_SEC; 431 dImplTicksPerSecond = nImplTicksPerSecond; 432 dImplTicksULONGMAX = (double)(sal_uIntPtr)ULONG_MAX; 433 } 434 435 double fTicks = nTicks; 436 fTicks *= 1000; 437 fTicks /= dImplTicksPerSecond; 438 fTicks = fmod (fTicks, dImplTicksULONGMAX); 439 return (sal_uIntPtr)fTicks; 440 #endif 441 } 442