LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/tools/source/datetime - ttime.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 136 182 74.7 %
Date: 2013-07-09 Functions: 16 22 72.7 %
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         480 :     sal_Int64 TimeToNanoSec( const Time& rTime )
      53             :     {
      54         480 :         short  nSign   = (rTime.GetTime() >= 0) ? +1 : -1;
      55         480 :         sal_Int32   nHour    = rTime.GetHour();
      56         480 :         sal_Int32   nMin     = rTime.GetMin();
      57         480 :         sal_Int32   nSec     = rTime.GetSec();
      58         480 :         sal_Int32   nNanoSec = rTime.GetNanoSec();
      59             : 
      60         480 :         sal_Int64 nRet = nNanoSec;
      61         480 :         nRet     +=            nSec * nanoSecInSec;
      62         480 :         nRet     +=       nMin * secInMin * nanoSecInSec;
      63         480 :         nRet     += nHour * minInHour * secInMin * nanoSecInSec;
      64             : 
      65         480 :         return (nRet * nSign);
      66             :     }
      67             : 
      68         240 :     Time NanoSecToTime( sal_Int64 nNanoSec )
      69             :     {
      70             :         short nSign;
      71         240 :         if ( nNanoSec < 0 )
      72             :         {
      73           2 :             nNanoSec *= -1;
      74           2 :             nSign = -1;
      75             :         }
      76             :         else
      77         238 :             nSign = 1;
      78             : 
      79         240 :         Time aTime( 0, 0, 0, nNanoSec );
      80         240 :         aTime.SetTime( aTime.GetTime() * nSign );
      81         240 :         return aTime;
      82             :     }
      83             : 
      84             : } // anonymous namespace
      85             : 
      86        5822 : Time::Time( TimeInitSystem )
      87             : {
      88             : #if defined( WNT )
      89             :     SYSTEMTIME aDateTime;
      90             :     GetLocalTime( &aDateTime );
      91             : 
      92             :     // construct time
      93             :     nTime = aDateTime.wHour         * hourMask +
      94             :             aDateTime.wMinute       * minMask +
      95             :             aDateTime.wSecond       * secMask +
      96             :             aDateTime.wMilliseconds * 1000000;
      97             : #else
      98             :     // determine time
      99             :     struct timespec tsTime;
     100             : #if defined( __MACH__ )
     101             :     // OS X does not have clock_gettime, use clock_get_time
     102             :     clock_serv_t cclock;
     103             :     mach_timespec_t mts;
     104             :     host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
     105             :     clock_get_time(cclock, &mts);
     106             :     mach_port_deallocate(mach_task_self(), cclock);
     107             :     tsTime.tv_sec  = mts.tv_sec;
     108             :     tsTime.tv_nsec = mts.tv_nsec;
     109             : #else
     110             :     // CLOCK_REALTIME should be supported
     111             :     // on any modern Unix, but be extra cautious
     112        5822 :     if (clock_gettime(CLOCK_REALTIME, &tsTime) != 0)
     113             :     {
     114             :         struct timeval tvTime;
     115           0 :         OSL_VERIFY( gettimeofday(&tvTime, NULL) != 0 );
     116           0 :         tsTime.tv_sec  = tvTime.tv_sec;
     117           0 :         tsTime.tv_nsec = tvTime.tv_usec * 1000;
     118             :     }
     119             : #endif // __MACH__
     120             : 
     121             :     // construct time
     122             :     struct tm aTime;
     123        5822 :     time_t nTmpTime = tsTime.tv_sec;
     124        5822 :     if ( localtime_r( &nTmpTime, &aTime ) )
     125             :     {
     126       11644 :         nTime = aTime.tm_hour * hourMask +
     127       11644 :                 aTime.tm_min  * minMask +
     128       11644 :                 aTime.tm_sec  * secMask +
     129        5822 :                 tsTime.tv_nsec;
     130             :     }
     131             :     else
     132           0 :         nTime = 0;
     133             : #endif // WNT
     134        5822 : }
     135             : 
     136        5274 : Time::Time( const Time& rTime )
     137             : {
     138        5274 :     nTime = rTime.nTime;
     139        5274 : }
     140             : 
     141        2286 : Time::Time( sal_uInt32 nHour, sal_uInt32 nMin, sal_uInt32 nSec, sal_uInt64 nNanoSec )
     142             : {
     143             :     // normalize time
     144        2286 :     nSec     += nNanoSec / nanoSecInSec;
     145        2286 :     nNanoSec %= nanoSecInSec;
     146        2286 :     nMin     += nSec / secInMin;
     147        2286 :     nSec     %= secInMin;
     148        2286 :     nHour    += nMin / minInHour;
     149        2286 :     nMin     %= minInHour;
     150             : 
     151             :     // construct time
     152             :     nTime = nNanoSec +
     153        4572 :             nSec  * secMask +
     154        4572 :             nMin  * minMask +
     155        4572 :             nHour * hourMask;
     156        2286 : }
     157             : 
     158         231 : void Time::SetHour( sal_uInt16 nNewHour )
     159             : {
     160         231 :     short  nSign          = (nTime >= 0) ? +1 : -1;
     161         231 :     sal_Int32   nMin      = GetMin();
     162         231 :     sal_Int32   nSec      = GetSec();
     163         231 :     sal_Int32   nNanoSec  = GetNanoSec();
     164             : 
     165         462 :     nTime = nSign *
     166         462 :             ( nNanoSec +
     167         462 :               nSec  * secMask +
     168         462 :               nMin  * minMask +
     169         462 :               nNewHour * hourMask );
     170         231 : }
     171             : 
     172          12 : void Time::SetMin( sal_uInt16 nNewMin )
     173             : {
     174          12 :     short  nSign          = (nTime >= 0) ? +1 : -1;
     175          12 :     sal_Int32   nHour     = GetHour();
     176          12 :     sal_Int32   nSec      = GetSec();
     177          12 :     sal_Int32   nNanoSec  = GetNanoSec();
     178             : 
     179             :     // no overflow
     180          12 :     nNewMin = nNewMin % minInHour;
     181             : 
     182          24 :     nTime = nSign *
     183          24 :             ( nNanoSec +
     184          24 :               nSec  * secMask +
     185          24 :               nNewMin  * minMask +
     186          24 :               nHour * hourMask );
     187          12 : }
     188             : 
     189         851 : void Time::SetSec( sal_uInt16 nNewSec )
     190             : {
     191         851 :     short       nSign     = (nTime >= 0) ? +1 : -1;
     192         851 :     sal_Int32   nHour     = GetHour();
     193         851 :     sal_Int32   nMin      = GetMin();
     194         851 :     sal_Int32   nNanoSec   = GetNanoSec();
     195             : 
     196             :     // no overflow
     197         851 :     nNewSec = nNewSec % secInMin;
     198             : 
     199        1702 :     nTime = nSign *
     200        1702 :             ( nNanoSec +
     201        1702 :               nNewSec  * secMask +
     202        1702 :               nMin  * minMask +
     203        1702 :               nHour * hourMask );
     204         851 : }
     205             : 
     206         839 : void Time::SetNanoSec( sal_uInt32 nNewNanoSec )
     207             : {
     208         839 :     short       nSign     = (nTime >= 0) ? +1 : -1;
     209         839 :     sal_Int32   nHour     = GetHour();
     210         839 :     sal_Int32   nMin      = GetMin();
     211         839 :     sal_Int32   nSec      = GetSec();
     212             : 
     213             :     // no overflow
     214         839 :     nNewNanoSec = nNewNanoSec % nanoSecInSec;
     215             : 
     216        1678 :     nTime = nSign *
     217        1678 :             ( nNewNanoSec +
     218        1678 :               nSec  * secMask +
     219        1678 :               nMin  * minMask +
     220        1678 :               nHour * hourMask );
     221         839 : }
     222             : 
     223        1122 : sal_Int64 Time::GetNSFromTime() const
     224             : {
     225        1122 :     short       nSign     = (nTime >= 0) ? +1 : -1;
     226        1122 :     sal_Int32   nHour     = GetHour();
     227        1122 :     sal_Int32   nMin      = GetMin();
     228        1122 :     sal_Int32   nSec      = GetSec();
     229        1122 :     sal_Int32   nNanoSec  = GetNanoSec();
     230             : 
     231        1122 :     return nSign *
     232        2244 :            ( nNanoSec +
     233        2244 :              nSec  * nanoSecInSec +
     234        2244 :              nMin  * (secInMin * nanoSecInSec) +
     235        2244 :              nHour * (minInHour * secInMin * nanoSecInSec) );
     236             : }
     237             : 
     238           0 : void Time::MakeTimeFromNS( sal_Int64 nNS )
     239             : {
     240             :     short nSign;
     241           0 :     if ( nNS < 0 )
     242             :     {
     243           0 :         nNS *= -1;
     244           0 :         nSign = -1;
     245             :     }
     246             :     else
     247           0 :         nSign = 1;
     248             : 
     249             :     // avoid overflow when sal_uIntPtr is 32 bits
     250           0 :     Time aTime( 0, 0, nNS/nanoSecInSec, nNS % nanoSecInSec );
     251           0 :     SetTime( aTime.GetTime() * nSign );
     252           0 : }
     253             : 
     254           0 : sal_Int32 Time::GetMSFromTime() const
     255             : {
     256           0 :     short       nSign     = (nTime >= 0) ? +1 : -1;
     257           0 :     sal_Int32   nHour     = GetHour();
     258           0 :     sal_Int32   nMin      = GetMin();
     259           0 :     sal_Int32   nSec      = GetSec();
     260           0 :     sal_Int32   nNanoSec  = GetNanoSec();
     261             : 
     262           0 :     return nSign *
     263           0 :            ( nNanoSec/1000000 +
     264           0 :              nSec  * 1000 +
     265           0 :              nMin  * 60000 +
     266           0 :              nHour * 360000 );
     267             : }
     268             : 
     269           0 : void Time::MakeTimeFromMS( sal_Int32 nMS )
     270             : {
     271             :     short nSign;
     272           0 :     if ( nMS < 0 )
     273             :     {
     274           0 :         nMS *= -1;
     275           0 :         nSign = -1;
     276             :     }
     277             :     else
     278           0 :         nSign = 1;
     279             : 
     280             :     // avoid overflow when sal_uIntPtr is 32 bits
     281           0 :     Time aTime( 0, 0, nMS/1000, (nMS % 1000) * 1000000 );
     282           0 :     SetTime( aTime.GetTime() * nSign );
     283           0 : }
     284             : 
     285           0 : double Time::GetTimeInDays() const
     286             : {
     287           0 :     short  nSign      = (nTime >= 0) ? +1 : -1;
     288           0 :     double nHour      = GetHour();
     289           0 :     double nMin       = GetMin();
     290           0 :     double nSec       = GetSec();
     291           0 :     double nNanoSec   = GetNanoSec();
     292             : 
     293           0 :     return (nHour + (nMin / 60) + (nSec / (minInHour * secInMin)) + (nNanoSec / (minInHour * secInMin * nanoSecInSec))) / 24 * nSign;
     294             : }
     295             : 
     296        3196 : Time& Time::operator =( const Time& rTime )
     297             : {
     298        3196 :     nTime = rTime.nTime;
     299        3196 :     return *this;
     300             : }
     301             : 
     302         205 : Time& Time::operator +=( const Time& rTime )
     303             : {
     304         205 :     nTime = NanoSecToTime( TimeToNanoSec( *this ) +
     305         205 :                            TimeToNanoSec( rTime ) ).GetTime();
     306         205 :     return *this;
     307             : }
     308             : 
     309          20 : Time& Time::operator -=( const Time& rTime )
     310             : {
     311          20 :     nTime = NanoSecToTime( TimeToNanoSec( *this ) -
     312          20 :                            TimeToNanoSec( rTime ) ).GetTime();
     313          20 :     return *this;
     314             : }
     315             : 
     316           0 : Time operator +( const Time& rTime1, const Time& rTime2 )
     317             : {
     318           0 :     return NanoSecToTime( TimeToNanoSec( rTime1 ) +
     319           0 :                           TimeToNanoSec( rTime2 ) );
     320             : }
     321             : 
     322          15 : Time operator -( const Time& rTime1, const Time& rTime2 )
     323             : {
     324          15 :     return NanoSecToTime( TimeToNanoSec( rTime1 ) -
     325          15 :                           TimeToNanoSec( rTime2 ) );
     326             : }
     327             : 
     328           0 : bool Time::IsEqualIgnoreNanoSec( const Time& rTime ) const
     329             : {
     330           0 :     sal_Int32 n1 = (nTime       < 0 ? -static_cast<sal_Int32>(GetNanoSec())       : GetNanoSec() );
     331           0 :     sal_Int32 n2 = (rTime.nTime < 0 ? -static_cast<sal_Int32>(rTime.GetNanoSec()) : rTime.GetNanoSec() );
     332           0 :     return (nTime - n1) == (rTime.nTime - n2);
     333             : }
     334             : 
     335         218 : Time Time::GetUTCOffset()
     336             : {
     337             : #if 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         218 :     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             :     // determine value again if needed
     361         426 :     if ( (nCacheSecOffset == -1)            ||
     362         416 :          ((nTicks - nCacheTicks) > 360000)  ||
     363         208 :          ( nTicks < nCacheTicks ) // handle overflow
     364             :          )
     365             :     {
     366          10 :         nTime = time( 0 );
     367          10 :         localtime_r( &nTime, &aTM );
     368          10 :         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          10 :         nUTC = nLocalTime - aTM.tm_gmtoff;
     376             : #else
     377             :          gmtime_r( &nTime, &aTM );
     378             :          nUTC = mktime( &aTM );
     379             : #endif
     380          10 :          nCacheTicks = nTicks;
     381          10 :          nCacheSecOffset = (nLocalTime-nUTC) / 60;
     382             :     }
     383             : 
     384         218 :     nTempTime = abs( nCacheSecOffset );
     385         218 :     Time aTime( 0, (sal_uInt16)nTempTime );
     386         218 :     if ( nCacheSecOffset < 0 )
     387           0 :         aTime = -aTime;
     388         218 :     return aTime;
     389             : #endif
     390             : }
     391             : 
     392      528438 : sal_uIntPtr Time::GetSystemTicks()
     393             : {
     394             : #if defined WNT
     395             :     return (sal_uIntPtr)GetTickCount();
     396             : #else
     397             :     timeval tv;
     398      528438 :     gettimeofday (&tv, 0);
     399             : 
     400      528438 :     double fTicks = tv.tv_sec;
     401      528438 :     fTicks *= 1000;
     402      528438 :     fTicks += ((tv.tv_usec + 500) / 1000);
     403             : 
     404      528438 :     fTicks = fmod (fTicks, double(ULONG_MAX));
     405      528438 :     return sal_uIntPtr(fTicks);
     406             : #endif
     407             : }
     408             : 
     409             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10