LCOV - code coverage report
Current view: top level - tools/source/datetime - ttime.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 146 188 77.7 %
Date: 2014-11-03 Functions: 19 24 79.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #if defined( WNT )
      21             : #include <windows.h>
      22             : #elif defined UNX
      23             : #include <unistd.h>
      24             : #include <limits.h>
      25             : #include <math.h>
      26             : #include <sys/time.h>
      27             : #endif
      28             : 
      29             : #include <time.h>
      30             : #ifdef __MACH__
      31             : #include <mach/clock.h>
      32             : #include <mach/mach.h>
      33             : #endif
      34             : #include <tools/time.hxx>
      35             : 
      36             : #include <osl/diagnose.h>
      37             : 
      38             : #if defined(SOLARIS) && defined(__GNUC__)
      39             : extern long altzone;
      40             : #endif
      41             : 
      42             : namespace {
      43             : 
      44             :     const sal_Int64 secMask  = SAL_CONST_INT64(1000000000);
      45             :     const sal_Int64 minMask  = SAL_CONST_INT64(100000000000);
      46             :     const sal_Int64 hourMask = SAL_CONST_INT64(10000000000000);
      47             : 
      48             :     const sal_Int64 nanoSecInSec = 1000000000;
      49             :     const sal_Int16 secInMin     = 60;
      50             :     const sal_Int16 minInHour    = 60;
      51             : 
      52        2028 :     sal_Int64 TimeToNanoSec( const tools::Time& rTime )
      53             :     {
      54        2028 :         short  nSign   = (rTime.GetTime() >= 0) ? +1 : -1;
      55        2028 :         sal_Int32   nHour    = rTime.GetHour();
      56        2028 :         sal_Int32   nMin     = rTime.GetMin();
      57        2028 :         sal_Int32   nSec     = rTime.GetSec();
      58        2028 :         sal_Int32   nNanoSec = rTime.GetNanoSec();
      59             : 
      60        2028 :         sal_Int64 nRet = nNanoSec;
      61        2028 :         nRet     +=            nSec * nanoSecInSec;
      62        2028 :         nRet     +=       nMin * secInMin * nanoSecInSec;
      63        2028 :         nRet     += nHour * minInHour * secInMin * nanoSecInSec;
      64             : 
      65        2028 :         return (nRet * nSign);
      66             :     }
      67             : 
      68        1014 :     tools::Time NanoSecToTime( sal_Int64 nNanoSec )
      69             :     {
      70             :         short nSign;
      71        1014 :         if ( nNanoSec < 0 )
      72             :         {
      73           0 :             nNanoSec *= -1;
      74           0 :             nSign = -1;
      75             :         }
      76             :         else
      77        1014 :             nSign = 1;
      78             : 
      79        1014 :         tools::Time aTime( 0, 0, 0, nNanoSec );
      80        1014 :         aTime.SetTime( aTime.GetTime() * nSign );
      81        1014 :         return aTime;
      82             :     }
      83             : 
      84             : } // anonymous namespace
      85             : 
      86             : namespace tools {
      87             : 
      88       30082 : Time::Time( TimeInitSystem )
      89             : {
      90             : #if defined( WNT )
      91             :     SYSTEMTIME aDateTime;
      92             :     GetLocalTime( &aDateTime );
      93             : 
      94             :     // construct time
      95             :     nTime = aDateTime.wHour         * hourMask +
      96             :             aDateTime.wMinute       * minMask +
      97             :             aDateTime.wSecond       * secMask +
      98             :             aDateTime.wMilliseconds * 1000000;
      99             : #else
     100             :     // determine time
     101             :     struct timespec tsTime;
     102             : #if defined( __MACH__ )
     103             :     // OS X does not have clock_gettime, use clock_get_time
     104             :     clock_serv_t cclock;
     105             :     mach_timespec_t mts;
     106             :     host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
     107             :     clock_get_time(cclock, &mts);
     108             :     mach_port_deallocate(mach_task_self(), cclock);
     109             :     tsTime.tv_sec  = mts.tv_sec;
     110             :     tsTime.tv_nsec = mts.tv_nsec;
     111             : #else
     112             :     // CLOCK_REALTIME should be supported
     113             :     // on any modern Unix, but be extra cautious
     114       30082 :     if (clock_gettime(CLOCK_REALTIME, &tsTime) != 0)
     115             :     {
     116             :         struct timeval tvTime;
     117           0 :         OSL_VERIFY( gettimeofday(&tvTime, NULL) != 0 );
     118           0 :         tsTime.tv_sec  = tvTime.tv_sec;
     119           0 :         tsTime.tv_nsec = tvTime.tv_usec * 1000;
     120             :     }
     121             : #endif // __MACH__
     122             : 
     123             :     // construct time
     124             :     struct tm aTime;
     125       30082 :     time_t nTmpTime = tsTime.tv_sec;
     126       30082 :     if ( localtime_r( &nTmpTime, &aTime ) )
     127             :     {
     128       60164 :         nTime = aTime.tm_hour * hourMask +
     129       60164 :                 aTime.tm_min  * minMask +
     130       60164 :                 aTime.tm_sec  * secMask +
     131       30082 :                 tsTime.tv_nsec;
     132             :     }
     133             :     else
     134           0 :         nTime = 0;
     135             : #endif // WNT
     136       30082 : }
     137             : 
     138       25644 : Time::Time( const tools::Time& rTime )
     139             : {
     140       25644 :     nTime = rTime.nTime;
     141       25644 : }
     142             : 
     143       10038 : Time::Time( sal_uInt32 nHour, sal_uInt32 nMin, sal_uInt32 nSec, sal_uInt64 nNanoSec )
     144             : {
     145       10038 :     init(nHour, nMin, nSec, nNanoSec);
     146       10038 : }
     147         210 : Time::Time( const ::com::sun::star::util::Time &_rTime )
     148             : {
     149         210 :     init(_rTime.Hours, _rTime.Minutes, _rTime.Seconds, _rTime.NanoSeconds);
     150         210 : }
     151       10248 : void tools::Time::init( sal_uInt32 nHour, sal_uInt32 nMin, sal_uInt32 nSec, sal_uInt64 nNanoSec )
     152             : {
     153             :     // normalize time
     154       10248 :     nSec     += nNanoSec / nanoSecInSec;
     155       10248 :     nNanoSec %= nanoSecInSec;
     156       10248 :     nMin     += nSec / secInMin;
     157       10248 :     nSec     %= secInMin;
     158       10248 :     nHour    += nMin / minInHour;
     159       10248 :     nMin     %= minInHour;
     160             : 
     161             :     // construct time
     162             :     nTime = nNanoSec +
     163       20496 :             nSec  * secMask +
     164       20496 :             nMin  * minMask +
     165       20496 :             nHour * hourMask;
     166       10248 : }
     167             : 
     168        1094 : void tools::Time::SetHour( sal_uInt16 nNewHour )
     169             : {
     170        1094 :     short  nSign          = (nTime >= 0) ? +1 : -1;
     171        1094 :     sal_Int32   nMin      = GetMin();
     172        1094 :     sal_Int32   nSec      = GetSec();
     173        1094 :     sal_Int32   nNanoSec  = GetNanoSec();
     174             : 
     175        2188 :     nTime = nSign *
     176        2188 :             ( nNanoSec +
     177        2188 :               nSec  * secMask +
     178        2188 :               nMin  * minMask +
     179        2188 :               nNewHour * hourMask );
     180        1094 : }
     181             : 
     182         130 : void tools::Time::SetMin( sal_uInt16 nNewMin )
     183             : {
     184         130 :     short  nSign          = (nTime >= 0) ? +1 : -1;
     185         130 :     sal_Int32   nHour     = GetHour();
     186         130 :     sal_Int32   nSec      = GetSec();
     187         130 :     sal_Int32   nNanoSec  = GetNanoSec();
     188             : 
     189             :     // no overflow
     190         130 :     nNewMin = nNewMin % minInHour;
     191             : 
     192         260 :     nTime = nSign *
     193         260 :             ( nNanoSec +
     194         260 :               nSec  * secMask +
     195         260 :               nNewMin  * minMask +
     196         260 :               nHour * hourMask );
     197         130 : }
     198             : 
     199        5290 : void tools::Time::SetSec( sal_uInt16 nNewSec )
     200             : {
     201        5290 :     short       nSign     = (nTime >= 0) ? +1 : -1;
     202        5290 :     sal_Int32   nHour     = GetHour();
     203        5290 :     sal_Int32   nMin      = GetMin();
     204        5290 :     sal_Int32   nNanoSec   = GetNanoSec();
     205             : 
     206             :     // no overflow
     207        5290 :     nNewSec = nNewSec % secInMin;
     208             : 
     209       10580 :     nTime = nSign *
     210       10580 :             ( nNanoSec +
     211       10580 :               nNewSec  * secMask +
     212       10580 :               nMin  * minMask +
     213       10580 :               nHour * hourMask );
     214        5290 : }
     215             : 
     216        5194 : void tools::Time::SetNanoSec( sal_uInt32 nNewNanoSec )
     217             : {
     218        5194 :     short       nSign     = (nTime >= 0) ? +1 : -1;
     219        5194 :     sal_Int32   nHour     = GetHour();
     220        5194 :     sal_Int32   nMin      = GetMin();
     221        5194 :     sal_Int32   nSec      = GetSec();
     222             : 
     223             :     // no overflow
     224        5194 :     nNewNanoSec = nNewNanoSec % nanoSecInSec;
     225             : 
     226       10388 :     nTime = nSign *
     227       10388 :             ( nNewNanoSec +
     228       10388 :               nSec  * secMask +
     229       10388 :               nMin  * minMask +
     230       10388 :               nHour * hourMask );
     231        5194 : }
     232             : 
     233        6768 : sal_Int64 tools::Time::GetNSFromTime() const
     234             : {
     235        6768 :     short       nSign     = (nTime >= 0) ? +1 : -1;
     236        6768 :     sal_Int32   nHour     = GetHour();
     237        6768 :     sal_Int32   nMin      = GetMin();
     238        6768 :     sal_Int32   nSec      = GetSec();
     239        6768 :     sal_Int32   nNanoSec  = GetNanoSec();
     240             : 
     241        6768 :     return nSign *
     242       13536 :            ( nNanoSec +
     243       13536 :              nSec  * nanoSecInSec +
     244       13536 :              nMin  * (secInMin * nanoSecInSec) +
     245       13536 :              nHour * (minInHour * secInMin * nanoSecInSec) );
     246             : }
     247             : 
     248           2 : void tools::Time::MakeTimeFromNS( sal_Int64 nNS )
     249             : {
     250             :     short nSign;
     251           2 :     if ( nNS < 0 )
     252             :     {
     253           0 :         nNS *= -1;
     254           0 :         nSign = -1;
     255             :     }
     256             :     else
     257           2 :         nSign = 1;
     258             : 
     259             :     // avoid overflow when sal_uIntPtr is 32 bits
     260           2 :     tools::Time aTime( 0, 0, nNS/nanoSecInSec, nNS % nanoSecInSec );
     261           2 :     SetTime( aTime.GetTime() * nSign );
     262           2 : }
     263             : 
     264           0 : sal_Int32 tools::Time::GetMSFromTime() const
     265             : {
     266           0 :     short       nSign     = (nTime >= 0) ? +1 : -1;
     267           0 :     sal_Int32   nHour     = GetHour();
     268           0 :     sal_Int32   nMin      = GetMin();
     269           0 :     sal_Int32   nSec      = GetSec();
     270           0 :     sal_Int32   nNanoSec  = GetNanoSec();
     271             : 
     272           0 :     return nSign *
     273           0 :            ( nNanoSec/1000000 +
     274           0 :              nSec  * 1000 +
     275           0 :              nMin  * 60000 +
     276           0 :              nHour * 360000 );
     277             : }
     278             : 
     279           0 : void tools::Time::MakeTimeFromMS( sal_Int32 nMS )
     280             : {
     281             :     short nSign;
     282           0 :     if ( nMS < 0 )
     283             :     {
     284           0 :         nMS *= -1;
     285           0 :         nSign = -1;
     286             :     }
     287             :     else
     288           0 :         nSign = 1;
     289             : 
     290             :     // avoid overflow when sal_uIntPtr is 32 bits
     291           0 :     tools::Time aTime( 0, 0, nMS/1000, (nMS % 1000) * 1000000 );
     292           0 :     SetTime( aTime.GetTime() * nSign );
     293           0 : }
     294             : 
     295           0 : double tools::Time::GetTimeInDays() const
     296             : {
     297           0 :     short  nSign      = (nTime >= 0) ? +1 : -1;
     298           0 :     double nHour      = GetHour();
     299           0 :     double nMin       = GetMin();
     300           0 :     double nSec       = GetSec();
     301           0 :     double nNanoSec   = GetNanoSec();
     302             : 
     303           0 :     return (nHour + (nMin / 60) + (nSec / (minInHour * secInMin)) + (nNanoSec / (minInHour * secInMin * nanoSecInSec))) / 24 * nSign;
     304             : }
     305             : 
     306       13138 : Time& tools::Time::operator =( const tools::Time& rTime )
     307             : {
     308       13138 :     nTime = rTime.nTime;
     309       13138 :     return *this;
     310             : }
     311             : 
     312         732 : Time& tools::Time::operator +=( const tools::Time& rTime )
     313             : {
     314         732 :     nTime = NanoSecToTime( TimeToNanoSec( *this ) +
     315         732 :                            TimeToNanoSec( rTime ) ).GetTime();
     316         732 :     return *this;
     317             : }
     318             : 
     319         244 : Time& tools::Time::operator -=( const tools::Time& rTime )
     320             : {
     321         244 :     nTime = NanoSecToTime( TimeToNanoSec( *this ) -
     322         244 :                            TimeToNanoSec( rTime ) ).GetTime();
     323         244 :     return *this;
     324             : }
     325             : 
     326           0 : Time operator +( const tools::Time& rTime1, const tools::Time& rTime2 )
     327             : {
     328           0 :     return NanoSecToTime( TimeToNanoSec( rTime1 ) +
     329           0 :                           TimeToNanoSec( rTime2 ) );
     330             : }
     331             : 
     332          38 : Time operator -( const tools::Time& rTime1, const tools::Time& rTime2 )
     333             : {
     334          38 :     return NanoSecToTime( TimeToNanoSec( rTime1 ) -
     335          38 :                           TimeToNanoSec( rTime2 ) );
     336             : }
     337             : 
     338           0 : bool tools::Time::IsEqualIgnoreNanoSec( const tools::Time& rTime ) const
     339             : {
     340           0 :     sal_Int32 n1 = (nTime       < 0 ? -static_cast<sal_Int32>(GetNanoSec())       : GetNanoSec() );
     341           0 :     sal_Int32 n2 = (rTime.nTime < 0 ? -static_cast<sal_Int32>(rTime.GetNanoSec()) : rTime.GetNanoSec() );
     342           0 :     return (nTime - n1) == (rTime.nTime - n2);
     343             : }
     344             : 
     345         954 : Time tools::Time::GetUTCOffset()
     346             : {
     347             : #if defined( WNT )
     348             :     TIME_ZONE_INFORMATION   aTimeZone;
     349             :     aTimeZone.Bias = 0;
     350             :     DWORD nTimeZoneRet = GetTimeZoneInformation( &aTimeZone );
     351             :     sal_Int32 nTempTime = aTimeZone.Bias;
     352             :     if ( nTimeZoneRet == TIME_ZONE_ID_STANDARD )
     353             :         nTempTime += aTimeZone.StandardBias;
     354             :     else if ( nTimeZoneRet == TIME_ZONE_ID_DAYLIGHT )
     355             :         nTempTime += aTimeZone.DaylightBias;
     356             :     tools::Time aTime( 0, (sal_uInt16)abs( nTempTime ) );
     357             :     if ( nTempTime > 0 )
     358             :         aTime = -aTime;
     359             :     return aTime;
     360             : #else
     361             :     static sal_uIntPtr  nCacheTicks = 0;
     362             :     static sal_Int32    nCacheSecOffset = -1;
     363         954 :     sal_uIntPtr         nTicks = tools::Time::GetSystemTicks();
     364             :     time_t          nTime;
     365             :     tm              aTM;
     366             :     sal_Int32           nLocalTime;
     367             :     sal_Int32           nUTC;
     368             :     short           nTempTime;
     369             : 
     370             :     // determine value again if needed
     371        1880 :     if ( (nCacheSecOffset == -1)            ||
     372        1852 :          ((nTicks - nCacheTicks) > 360000)  ||
     373         926 :          ( nTicks < nCacheTicks ) // handle overflow
     374             :          )
     375             :     {
     376          28 :         nTime = time( 0 );
     377          28 :         localtime_r( &nTime, &aTM );
     378          28 :         nLocalTime = mktime( &aTM );
     379             : #if defined( SOLARIS )
     380             :         // Solaris gmtime_r() seems not to handle daylight saving time
     381             :         // flags correctly
     382             :         nUTC = nLocalTime + ( aTM.tm_isdst == 0 ? timezone : altzone );
     383             : #elif defined( LINUX )
     384             :         // Linux mktime() seems not to handle tm_isdst correctly
     385          28 :         nUTC = nLocalTime - aTM.tm_gmtoff;
     386             : #else
     387             :          gmtime_r( &nTime, &aTM );
     388             :          nUTC = mktime( &aTM );
     389             : #endif
     390          28 :          nCacheTicks = nTicks;
     391          28 :          nCacheSecOffset = (nLocalTime-nUTC) / 60;
     392             :     }
     393             : 
     394         954 :     nTempTime = abs( nCacheSecOffset );
     395         954 :     tools::Time aTime( 0, (sal_uInt16)nTempTime );
     396         954 :     if ( nCacheSecOffset < 0 )
     397           0 :         aTime = -aTime;
     398         954 :     return aTime;
     399             : #endif
     400             : }
     401             : 
     402     1367631 : sal_uIntPtr tools::Time::GetSystemTicks()
     403             : {
     404             : #if defined WNT
     405             :     static LARGE_INTEGER nTicksPerSecond;
     406             :     static bool bTicksPerSecondInitialized = false;
     407             :     if (!bTicksPerSecondInitialized)
     408             :     {
     409             :         QueryPerformanceFrequency(&nTicksPerSecond);
     410             :         bTicksPerSecondInitialized = true;
     411             :     }
     412             : 
     413             :     LARGE_INTEGER nPerformanceCount;
     414             :     QueryPerformanceCounter(&nPerformanceCount);
     415             : 
     416             :     return (sal_uIntPtr)((nPerformanceCount.QuadPart*1000)/nTicksPerSecond.QuadPart);
     417             : #else
     418             :     timeval tv;
     419     1367631 :     gettimeofday (&tv, 0);
     420             : 
     421     1367631 :     double fTicks = tv.tv_sec;
     422     1367631 :     fTicks *= 1000;
     423     1367631 :     fTicks += ((tv.tv_usec + 500) / 1000);
     424             : 
     425     1367631 :     fTicks = fmod (fTicks, double(ULONG_MAX));
     426     1367631 :     return sal_uIntPtr(fTicks);
     427             : #endif
     428             : }
     429             : 
     430             : } /* namespace tools */
     431             : 
     432             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10