1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
35 #include <mach/clock.h>
36 #include <mach/mach.h>
39 #include <sal/log.hxx>
40 #include <tools/time.hxx>
41 #include <osl/diagnose.h>
43 #if defined(SOLARIS) && defined(__GNUC__)
49 const sal_Int64 secMask
= SAL_CONST_INT64(1000000000);
50 const sal_Int64 minMask
= SAL_CONST_INT64(100000000000);
51 const sal_Int64 hourMask
= SAL_CONST_INT64(10000000000000);
53 const sal_Int64 nanoSecInSec
= 1000000000;
54 const sal_Int16 secInMin
= 60;
55 const sal_Int16 minInHour
= 60;
57 sal_Int64
TimeToNanoSec( const tools::Time
& rTime
)
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 nNanoSec
= rTime
.GetNanoSec();
65 sal_Int64 nRet
= nNanoSec
;
66 nRet
+= nSec
* nanoSecInSec
;
67 nRet
+= nMin
* secInMin
* nanoSecInSec
;
68 nRet
+= nHour
* minInHour
* secInMin
* nanoSecInSec
;
70 return (nRet
* nSign
);
73 tools::Time
NanoSecToTime( sal_Int64 nNanoSec
)
84 tools::Time
aTime( 0, 0, 0, nNanoSec
);
85 aTime
.SetTime( aTime
.GetTime() * nSign
);
89 } // anonymous namespace
93 Time::Time( TimeInitSystem
)
97 GetLocalTime( &aDateTime
);
100 nTime
= aDateTime
.wHour
* hourMask
+
101 aDateTime
.wMinute
* minMask
+
102 aDateTime
.wSecond
* secMask
+
103 aDateTime
.wMilliseconds
* 1000000;
106 struct timespec tsTime
;
107 #if defined( __MACH__ )
108 // OS X does not have clock_gettime, use clock_get_time
111 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK
, &cclock
);
112 clock_get_time(cclock
, &mts
);
113 mach_port_deallocate(mach_task_self(), cclock
);
114 tsTime
.tv_sec
= mts
.tv_sec
;
115 tsTime
.tv_nsec
= mts
.tv_nsec
;
117 // CLOCK_REALTIME should be supported
118 // on any modern Unix, but be extra cautious
119 if (clock_gettime(CLOCK_REALTIME
, &tsTime
) != 0)
121 struct timeval tvTime
;
122 OSL_VERIFY( gettimeofday(&tvTime
, NULL
) != 0 );
123 tsTime
.tv_sec
= tvTime
.tv_sec
;
124 tsTime
.tv_nsec
= tvTime
.tv_usec
* 1000;
130 time_t nTmpTime
= tsTime
.tv_sec
;
131 if ( localtime_r( &nTmpTime
, &aTime
) )
133 nTime
= aTime
.tm_hour
* hourMask
+
134 aTime
.tm_min
* minMask
+
135 aTime
.tm_sec
* secMask
+
143 Time::Time( const tools::Time
& rTime
)
148 Time::Time( sal_uInt32 nHour
, sal_uInt32 nMin
, sal_uInt32 nSec
, sal_uInt64 nNanoSec
)
150 init(nHour
, nMin
, nSec
, nNanoSec
);
152 Time::Time( const ::com::sun::star::util::Time
&_rTime
)
154 init(_rTime
.Hours
, _rTime
.Minutes
, _rTime
.Seconds
, _rTime
.NanoSeconds
);
156 Time::Time( const ::com::sun::star::util::DateTime
&_rDateTime
)
158 init(_rDateTime
.Hours
, _rDateTime
.Minutes
, _rDateTime
.Seconds
, _rDateTime
.NanoSeconds
);
161 void tools::Time::init( sal_uInt32 nHour
, sal_uInt32 nMin
, sal_uInt32 nSec
, sal_uInt64 nNanoSec
)
164 nSec
+= nNanoSec
/ nanoSecInSec
;
165 nNanoSec
%= nanoSecInSec
;
166 nMin
+= nSec
/ secInMin
;
168 nHour
+= nMin
/ minInHour
;
178 void tools::Time::SetHour( sal_uInt16 nNewHour
)
180 short nSign
= (nTime
>= 0) ? +1 : -1;
181 sal_Int32 nMin
= GetMin();
182 sal_Int32 nSec
= GetSec();
183 sal_Int32 nNanoSec
= GetNanoSec();
189 nNewHour
* hourMask
);
192 void tools::Time::SetMin( sal_uInt16 nNewMin
)
194 short nSign
= (nTime
>= 0) ? +1 : -1;
195 sal_Int32 nHour
= GetHour();
196 sal_Int32 nSec
= GetSec();
197 sal_Int32 nNanoSec
= GetNanoSec();
200 nNewMin
= nNewMin
% minInHour
;
209 void tools::Time::SetSec( sal_uInt16 nNewSec
)
211 short nSign
= (nTime
>= 0) ? +1 : -1;
212 sal_Int32 nHour
= GetHour();
213 sal_Int32 nMin
= GetMin();
214 sal_Int32 nNanoSec
= GetNanoSec();
217 nNewSec
= nNewSec
% secInMin
;
226 void tools::Time::SetNanoSec( sal_uInt32 nNewNanoSec
)
228 short nSign
= (nTime
>= 0) ? +1 : -1;
229 sal_Int32 nHour
= GetHour();
230 sal_Int32 nMin
= GetMin();
231 sal_Int32 nSec
= GetSec();
234 nNewNanoSec
= nNewNanoSec
% nanoSecInSec
;
243 sal_Int64
tools::Time::GetNSFromTime() const
245 short nSign
= (nTime
>= 0) ? +1 : -1;
246 sal_Int32 nHour
= GetHour();
247 sal_Int32 nMin
= GetMin();
248 sal_Int32 nSec
= GetSec();
249 sal_Int32 nNanoSec
= GetNanoSec();
253 nSec
* nanoSecInSec
+
254 nMin
* (secInMin
* nanoSecInSec
) +
255 nHour
* (minInHour
* secInMin
* nanoSecInSec
) );
258 void tools::Time::MakeTimeFromNS( sal_Int64 nNS
)
269 // avoid overflow when sal_uIntPtr is 32 bits
270 tools::Time
aTime( 0, 0, nNS
/nanoSecInSec
, nNS
% nanoSecInSec
);
271 SetTime( aTime
.GetTime() * nSign
);
274 sal_Int32
tools::Time::GetMSFromTime() const
276 short nSign
= (nTime
>= 0) ? +1 : -1;
277 sal_Int32 nHour
= GetHour();
278 sal_Int32 nMin
= GetMin();
279 sal_Int32 nSec
= GetSec();
280 sal_Int32 nNanoSec
= GetNanoSec();
289 void tools::Time::MakeTimeFromMS( sal_Int32 nMS
)
300 // avoid overflow when sal_uIntPtr is 32 bits
301 tools::Time
aTime( 0, 0, nMS
/1000, (nMS
% 1000) * 1000000 );
302 SetTime( aTime
.GetTime() * nSign
);
305 double tools::Time::GetTimeInDays() const
307 short nSign
= (nTime
>= 0) ? +1 : -1;
308 double nHour
= GetHour();
309 double nMin
= GetMin();
310 double nSec
= GetSec();
311 double nNanoSec
= GetNanoSec();
313 return (nHour
+ (nMin
/ 60) + (nSec
/ (minInHour
* secInMin
)) + (nNanoSec
/ (minInHour
* secInMin
* nanoSecInSec
))) / 24 * nSign
;
316 Time
& tools::Time::operator =( const tools::Time
& rTime
)
322 Time
& tools::Time::operator +=( const tools::Time
& rTime
)
324 nTime
= NanoSecToTime( TimeToNanoSec( *this ) +
325 TimeToNanoSec( rTime
) ).GetTime();
329 Time
& tools::Time::operator -=( const tools::Time
& rTime
)
331 nTime
= NanoSecToTime( TimeToNanoSec( *this ) -
332 TimeToNanoSec( rTime
) ).GetTime();
336 Time
operator +( const tools::Time
& rTime1
, const tools::Time
& rTime2
)
338 return NanoSecToTime( TimeToNanoSec( rTime1
) +
339 TimeToNanoSec( rTime2
) );
342 Time
operator -( const tools::Time
& rTime1
, const tools::Time
& rTime2
)
344 return NanoSecToTime( TimeToNanoSec( rTime1
) -
345 TimeToNanoSec( rTime2
) );
348 bool tools::Time::IsEqualIgnoreNanoSec( const tools::Time
& rTime
) const
350 sal_Int32 n1
= (nTime
< 0 ? -static_cast<sal_Int32
>(GetNanoSec()) : GetNanoSec() );
351 sal_Int32 n2
= (rTime
.nTime
< 0 ? -static_cast<sal_Int32
>(rTime
.GetNanoSec()) : rTime
.GetNanoSec() );
352 return (nTime
- n1
) == (rTime
.nTime
- n2
);
355 Time
tools::Time::GetUTCOffset()
358 TIME_ZONE_INFORMATION aTimeZone
;
360 DWORD nTimeZoneRet
= GetTimeZoneInformation( &aTimeZone
);
361 sal_Int32 nTempTime
= aTimeZone
.Bias
;
362 if ( nTimeZoneRet
== TIME_ZONE_ID_STANDARD
)
363 nTempTime
+= aTimeZone
.StandardBias
;
364 else if ( nTimeZoneRet
== TIME_ZONE_ID_DAYLIGHT
)
365 nTempTime
+= aTimeZone
.DaylightBias
;
366 tools::Time
aTime( 0, (sal_uInt16
)abs( nTempTime
) );
371 static sal_uInt64 nCacheTicks
= 0;
372 static sal_Int32 nCacheSecOffset
= -1;
373 sal_uInt64 nTicks
= tools::Time::GetSystemTicks();
376 sal_Int32 nLocalTime
;
380 // determine value again if needed
381 if ( (nCacheSecOffset
== -1) ||
382 ((nTicks
- nCacheTicks
) > 360000) ||
383 ( nTicks
< nCacheTicks
) // handle overflow
387 localtime_r( &nTime
, &aTM
);
388 nLocalTime
= mktime( &aTM
);
389 #if defined( SOLARIS )
390 // Solaris gmtime_r() seems not to handle daylight saving time
392 nUTC
= nLocalTime
+ ( aTM
.tm_isdst
== 0 ? timezone
: altzone
);
393 #elif defined( LINUX )
394 // Linux mktime() seems not to handle tm_isdst correctly
395 nUTC
= nLocalTime
- aTM
.tm_gmtoff
;
397 gmtime_r( &nTime
, &aTM
);
398 nUTC
= mktime( &aTM
);
400 nCacheTicks
= nTicks
;
401 nCacheSecOffset
= (nLocalTime
-nUTC
) / 60;
404 nTempTime
= abs( nCacheSecOffset
);
405 tools::Time
aTime( 0, (sal_uInt16
)nTempTime
);
406 if ( nCacheSecOffset
< 0 )
412 sal_uInt64
tools::Time::GetSystemTicks()
415 static LARGE_INTEGER nTicksPerSecond
;
416 static bool bTicksPerSecondInitialized
= false;
417 if (!bTicksPerSecondInitialized
)
419 QueryPerformanceFrequency(&nTicksPerSecond
);
420 bTicksPerSecondInitialized
= true;
423 LARGE_INTEGER nPerformanceCount
;
424 QueryPerformanceCounter(&nPerformanceCount
);
426 return static_cast<sal_uInt64
>(
427 (nPerformanceCount
.QuadPart
*1000)/nTicksPerSecond
.QuadPart
);
430 int n
= gettimeofday (&tv
, 0);
433 SAL_WARN("tools.datetime", "gettimeofday failed: " << e
);
435 return static_cast<sal_uInt64
>(tv
.tv_sec
) * 1000
436 + (static_cast<sal_uInt64
>(tv
.tv_usec
) + 500) / 1000;
440 } /* namespace tools */
442 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */