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