fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / tools / source / datetime / ttime.cxx
blob47dd81b144b026601362320519cbc4565c0cf62b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <cerrno>
24 #if defined( WNT )
25 #include <windows.h>
26 #elif defined UNX
27 #include <unistd.h>
28 #include <limits.h>
29 #include <math.h>
30 #include <sys/time.h>
31 #endif
33 #include <time.h>
34 #ifdef __MACH__
35 #include <mach/clock.h>
36 #include <mach/mach.h>
37 #endif
39 #include <sal/log.hxx>
40 #include <tools/time.hxx>
41 #include <osl/diagnose.h>
43 #if defined(SOLARIS) && defined(__GNUC__)
44 extern long altzone;
45 #endif
47 namespace {
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 )
75 short nSign;
76 if ( nNanoSec < 0 )
78 nNanoSec *= -1;
79 nSign = -1;
81 else
82 nSign = 1;
84 tools::Time aTime( 0, 0, 0, nNanoSec );
85 aTime.SetTime( aTime.GetTime() * nSign );
86 return aTime;
89 } // anonymous namespace
91 namespace tools {
93 Time::Time( TimeInitSystem )
95 #if defined( WNT )
96 SYSTEMTIME aDateTime;
97 GetLocalTime( &aDateTime );
99 // construct time
100 nTime = aDateTime.wHour * hourMask +
101 aDateTime.wMinute * minMask +
102 aDateTime.wSecond * secMask +
103 aDateTime.wMilliseconds * 1000000;
104 #else
105 // determine time
106 struct timespec tsTime;
107 #if defined( __MACH__ )
108 // OS X does not have clock_gettime, use clock_get_time
109 clock_serv_t cclock;
110 mach_timespec_t mts;
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;
116 #else
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;
126 #endif // __MACH__
128 // construct time
129 struct tm aTime;
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 +
136 tsTime.tv_nsec;
138 else
139 nTime = 0;
140 #endif // WNT
143 Time::Time( const tools::Time& rTime )
145 nTime = rTime.nTime;
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 )
163 // normalize time
164 nSec += nNanoSec / nanoSecInSec;
165 nNanoSec %= nanoSecInSec;
166 nMin += nSec / secInMin;
167 nSec %= secInMin;
168 nHour += nMin / minInHour;
169 nMin %= minInHour;
171 // construct time
172 nTime = nNanoSec +
173 nSec * secMask +
174 nMin * minMask +
175 nHour * hourMask;
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();
185 nTime = nSign *
186 ( nNanoSec +
187 nSec * secMask +
188 nMin * minMask +
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();
199 // no overflow
200 nNewMin = nNewMin % minInHour;
202 nTime = nSign *
203 ( nNanoSec +
204 nSec * secMask +
205 nNewMin * minMask +
206 nHour * hourMask );
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();
216 // no overflow
217 nNewSec = nNewSec % secInMin;
219 nTime = nSign *
220 ( nNanoSec +
221 nNewSec * secMask +
222 nMin * minMask +
223 nHour * hourMask );
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();
233 // no overflow
234 nNewNanoSec = nNewNanoSec % nanoSecInSec;
236 nTime = nSign *
237 ( nNewNanoSec +
238 nSec * secMask +
239 nMin * minMask +
240 nHour * hourMask );
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();
251 return nSign *
252 ( nNanoSec +
253 nSec * nanoSecInSec +
254 nMin * (secInMin * nanoSecInSec) +
255 nHour * (minInHour * secInMin * nanoSecInSec) );
258 void tools::Time::MakeTimeFromNS( sal_Int64 nNS )
260 short nSign;
261 if ( nNS < 0 )
263 nNS *= -1;
264 nSign = -1;
266 else
267 nSign = 1;
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();
282 return nSign *
283 ( nNanoSec/1000000 +
284 nSec * 1000 +
285 nMin * 60000 +
286 nHour * 360000 );
289 void tools::Time::MakeTimeFromMS( sal_Int32 nMS )
291 short nSign;
292 if ( nMS < 0 )
294 nMS *= -1;
295 nSign = -1;
297 else
298 nSign = 1;
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 )
318 nTime = rTime.nTime;
319 return *this;
322 Time& tools::Time::operator +=( const tools::Time& rTime )
324 nTime = NanoSecToTime( TimeToNanoSec( *this ) +
325 TimeToNanoSec( rTime ) ).GetTime();
326 return *this;
329 Time& tools::Time::operator -=( const tools::Time& rTime )
331 nTime = NanoSecToTime( TimeToNanoSec( *this ) -
332 TimeToNanoSec( rTime ) ).GetTime();
333 return *this;
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()
357 #if defined( WNT )
358 TIME_ZONE_INFORMATION aTimeZone;
359 aTimeZone.Bias = 0;
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 ) );
367 if ( nTempTime > 0 )
368 aTime = -aTime;
369 return aTime;
370 #else
371 static sal_uInt64 nCacheTicks = 0;
372 static sal_Int32 nCacheSecOffset = -1;
373 sal_uInt64 nTicks = tools::Time::GetSystemTicks();
374 time_t nTime;
375 tm aTM;
376 sal_Int32 nLocalTime;
377 sal_Int32 nUTC;
378 short nTempTime;
380 // determine value again if needed
381 if ( (nCacheSecOffset == -1) ||
382 ((nTicks - nCacheTicks) > 360000) ||
383 ( nTicks < nCacheTicks ) // handle overflow
386 nTime = time( 0 );
387 localtime_r( &nTime, &aTM );
388 nLocalTime = mktime( &aTM );
389 #if defined( SOLARIS )
390 // Solaris gmtime_r() seems not to handle daylight saving time
391 // flags correctly
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;
396 #else
397 gmtime_r( &nTime, &aTM );
398 nUTC = mktime( &aTM );
399 #endif
400 nCacheTicks = nTicks;
401 nCacheSecOffset = (nLocalTime-nUTC) / 60;
404 nTempTime = abs( nCacheSecOffset );
405 tools::Time aTime( 0, (sal_uInt16)nTempTime );
406 if ( nCacheSecOffset < 0 )
407 aTime = -aTime;
408 return aTime;
409 #endif
412 sal_uInt64 tools::Time::GetSystemTicks()
414 #if defined WNT
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);
428 #else
429 timeval tv;
430 int n = gettimeofday (&tv, 0);
431 if (n == -1) {
432 int e = errno;
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;
437 #endif
440 } /* namespace tools */
442 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */