xref: /AOO41X/main/tools/source/datetime/ttime.cxx (revision 27ead02a196d97d5a019233dfa246fc43dc6196d)
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