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