xref: /aoo41x/main/tools/source/datetime/ttime.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_tools.hxx"
30 
31 #define _TOOLS_TIME_CXX
32 
33 #if defined( OS2 )
34 #define INCL_DOSMISC
35 #define INCL_DOSDATETIME
36 #include <svpm.h>
37 #elif defined( WNT )
38 #ifdef _MSC_VER
39 #pragma warning (push,1)
40 #endif
41 #include <tools/svwin.h>
42 #ifdef _MSC_VER
43 #pragma warning (pop)
44 #endif
45 #elif defined UNX
46 #include <unistd.h>
47 #include <limits.h>
48 #include <math.h>
49 #include <sys/time.h>
50 #endif
51 
52 #include <time.h>
53 #include <tools/time.hxx>
54 
55 #if defined(SOLARIS) && defined(__GNUC__)
56 extern long altzone;
57 #endif
58 
59 // =======================================================================
60 
61 static sal_Int32 TimeToSec100( const Time& rTime )
62 {
63 	short  nSign   = (rTime.GetTime() >= 0) ? +1 : -1;
64 	sal_Int32   nHour   = rTime.GetHour();
65 	sal_Int32   nMin    = rTime.GetMin();
66 	sal_Int32   nSec    = rTime.GetSec();
67 	sal_Int32   n100Sec = rTime.Get100Sec();
68 
69 //	Wegen Interal Compiler Error bei MSC, etwas komplizierter
70 //	return (n100Sec + (nSec*100) + (nMin*60*100) + (nHour*60*60*100) * nSign);
71 
72 	sal_Int32 nRet = n100Sec;
73 	nRet	 += nSec*100;
74 	nRet	 += nMin*60*100;
75 	nRet	 += nHour*60*60*100;
76 
77 	return (nRet * nSign);
78 }
79 
80 // -----------------------------------------------------------------------
81 
82 static Time Sec100ToTime( sal_Int32 nSec100 )
83 {
84 	short nSign;
85 	if ( nSec100 < 0 )
86 	{
87 		nSec100 *= -1;
88 		nSign = -1;
89 	}
90 	else
91 		nSign = 1;
92 
93 	Time aTime( 0, 0, 0, nSec100 );
94 	aTime.SetTime( aTime.GetTime() * nSign );
95 	return aTime;
96 }
97 
98 // =======================================================================
99 
100 Time::Time()
101 {
102 #if defined( OS2 )
103 	DATETIME aDateTime;
104 	DosGetDateTime( &aDateTime );
105 
106 	// Zeit zusammenbauen
107 	nTime = (((sal_Int32)aDateTime.hours)*1000000) +
108 			(((sal_Int32)aDateTime.minutes)*10000) +
109 			(((sal_Int32)aDateTime.seconds)*100) +
110 			((sal_Int32)aDateTime.hundredths);
111 #elif defined( WNT )
112 	SYSTEMTIME aDateTime;
113 	GetLocalTime( &aDateTime );
114 
115 	// Zeit zusammenbauen
116 	nTime = (((sal_Int32)aDateTime.wHour)*1000000) +
117 			(((sal_Int32)aDateTime.wMinute)*10000) +
118 			(((sal_Int32)aDateTime.wSecond)*100) +
119 			((sal_Int32)aDateTime.wMilliseconds/10);
120 #else
121 	time_t	   nTmpTime;
122 	struct tm aTime;
123 
124 	// Zeit ermitteln
125 	nTmpTime = time( 0 );
126 
127 	// Zeit zusammenbauen
128 	if ( localtime_r( &nTmpTime, &aTime ) )
129 	{
130 		nTime = (((sal_Int32)aTime.tm_hour)*1000000) +
131 				(((sal_Int32)aTime.tm_min)*10000) +
132 				(((sal_Int32)aTime.tm_sec)*100);
133 	}
134 	else
135 		nTime = 0;
136 #endif
137 }
138 
139 // -----------------------------------------------------------------------
140 
141 Time::Time( const Time& rTime )
142 {
143 	nTime = rTime.nTime;
144 }
145 
146 // -----------------------------------------------------------------------
147 
148 Time::Time( sal_uIntPtr nHour, sal_uIntPtr nMin, sal_uIntPtr nSec, sal_uIntPtr n100Sec )
149 {
150 	// Zeit normalisieren
151 	nSec	+= n100Sec / 100;
152 	n100Sec  = n100Sec % 100;
153 	nMin	+= nSec / 60;
154 	nSec	 = nSec % 60;
155 	nHour	+= nMin / 60;
156 	nMin	 = nMin % 60;
157 
158 	// Zeit zusammenbauen
159 	nTime = (sal_Int32)(n100Sec + (nSec*100) + (nMin*10000) + (nHour*1000000));
160 }
161 
162 // -----------------------------------------------------------------------
163 
164 void Time::SetHour( sal_uInt16 nNewHour )
165 {
166 	short  nSign	  = (nTime >= 0) ? +1 : -1;
167 	sal_Int32   nMin 	  = GetMin();
168 	sal_Int32   nSec 	  = GetSec();
169 	sal_Int32   n100Sec	  = Get100Sec();
170 
171 	nTime = (n100Sec + (nSec*100) + (nMin*10000) +
172 			(((sal_Int32)nNewHour)*1000000)) * nSign;
173 }
174 
175 // -----------------------------------------------------------------------
176 
177 void Time::SetMin( sal_uInt16 nNewMin )
178 {
179 	short  nSign	  = (nTime >= 0) ? +1 : -1;
180 	sal_Int32   nHour	  = GetHour();
181 	sal_Int32   nSec 	  = GetSec();
182 	sal_Int32   n100Sec	  = Get100Sec();
183 
184 	// kein Ueberlauf
185 	nNewMin = nNewMin % 60;
186 
187 	nTime = (n100Sec + (nSec*100) + (((sal_Int32)nNewMin)*10000) +
188 			(nHour*1000000)) * nSign;
189 }
190 
191 // -----------------------------------------------------------------------
192 
193 void Time::SetSec( sal_uInt16 nNewSec )
194 {
195 	short       nSign	  = (nTime >= 0) ? +1 : -1;
196 	sal_Int32   nHour	  = GetHour();
197 	sal_Int32   nMin 	  = GetMin();
198 	sal_Int32   n100Sec	  = Get100Sec();
199 
200 	// kein Ueberlauf
201 	nNewSec = nNewSec % 60;
202 
203 	nTime = (n100Sec + (((sal_Int32)nNewSec)*100) + (nMin*10000) +
204 			(nHour*1000000)) * nSign;
205 }
206 
207 // -----------------------------------------------------------------------
208 
209 void Time::Set100Sec( sal_uInt16 nNew100Sec )
210 {
211 	short       nSign	  = (nTime >= 0) ? +1 : -1;
212 	sal_Int32   nHour	  = GetHour();
213 	sal_Int32   nMin 	  = GetMin();
214 	sal_Int32   nSec 	  = GetSec();
215 
216 	// kein Ueberlauf
217 	nNew100Sec = nNew100Sec % 100;
218 
219 	nTime = (((sal_Int32)nNew100Sec) + (nSec*100) + (nMin*10000) +
220 			(nHour*1000000)) * nSign;
221 }
222 
223 // -----------------------------------------------------------------------
224 
225 sal_Int32 Time::GetMSFromTime() const
226 {
227 	short       nSign	  = (nTime >= 0) ? +1 : -1;
228 	sal_Int32   nHour	  = GetHour();
229 	sal_Int32   nMin 	  = GetMin();
230 	sal_Int32   nSec 	  = GetSec();
231 	sal_Int32   n100Sec	  = Get100Sec();
232 
233 	return (((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10))*nSign);
234 }
235 
236 // -----------------------------------------------------------------------
237 
238 void Time::MakeTimeFromMS( sal_Int32 nMS )
239 {
240 	short nSign;
241 	if ( nMS < 0 )
242 	{
243 		nMS *= -1;
244 		nSign = -1;
245 	}
246 	else
247 		nSign = 1;
248 
249 	Time aTime( 0, 0, 0, nMS/10 );
250 	SetTime( aTime.GetTime() * nSign );
251 }
252 
253 // -----------------------------------------------------------------------
254 
255 double Time::GetTimeInDays() const
256 {
257 	short  nSign	  = (nTime >= 0) ? +1 : -1;
258     double nHour      = GetHour();
259     double nMin       = GetMin();
260     double nSec       = GetSec();
261     double n100Sec    = Get100Sec();
262 
263     return (nHour+(nMin/60)+(nSec/(60*60))+(n100Sec/(60*60*100))) / 24 * nSign;
264 }
265 
266 // -----------------------------------------------------------------------
267 
268 Time& Time::operator =( const Time& rTime )
269 {
270 	nTime = rTime.nTime;
271 	return *this;
272 }
273 
274 // -----------------------------------------------------------------------
275 
276 Time& Time::operator +=( const Time& rTime )
277 {
278 	nTime = Sec100ToTime( TimeToSec100( *this ) +
279 						  TimeToSec100( rTime ) ).GetTime();
280 	return *this;
281 }
282 
283 // -----------------------------------------------------------------------
284 
285 Time& Time::operator -=( const Time& rTime )
286 {
287 	nTime = Sec100ToTime( TimeToSec100( *this ) -
288 						  TimeToSec100( rTime ) ).GetTime();
289 	return *this;
290 }
291 
292 // -----------------------------------------------------------------------
293 
294 Time operator +( const Time& rTime1, const Time& rTime2 )
295 {
296 	return Sec100ToTime( TimeToSec100( rTime1 ) +
297 						 TimeToSec100( rTime2 ) );
298 }
299 
300 // -----------------------------------------------------------------------
301 
302 Time operator -( const Time& rTime1, const Time& rTime2 )
303 {
304 	return Sec100ToTime( TimeToSec100( rTime1 ) -
305 						 TimeToSec100( rTime2 ) );
306 }
307 
308 // -----------------------------------------------------------------------
309 
310 sal_Bool Time::IsEqualIgnore100Sec( const Time& rTime ) const
311 {
312     sal_Int32 n1 = (nTime < 0 ? -Get100Sec() : Get100Sec() );
313     sal_Int32 n2 = (rTime.nTime < 0 ? -rTime.Get100Sec() : rTime.Get100Sec() );
314     return (nTime - n1) == (rTime.nTime - n2);
315 }
316 
317 // -----------------------------------------------------------------------
318 
319 Time Time::GetUTCOffset()
320 {
321 #if defined( OS2 )
322 #undef timezone
323 	DATETIME aDateTime;
324 	DosGetDateTime( &aDateTime );
325 
326 	// Zeit zusammenbauen
327 	if ( aDateTime.timezone != -1  )
328 	{
329 		short nTempTime = (short)Abs( aDateTime.timezone );
330 		Time aTime( 0, (sal_uInt16)nTempTime );
331 		if ( aDateTime.timezone > 0 )
332 			aTime = -aTime;
333 		return aTime;
334 	}
335 	else
336 		return Time( 0 );
337 #elif 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 	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 	// Evt. Wert neu ermitteln
361 	if ( (nCacheSecOffset == -1)			||
362 		 ((nTicks - nCacheTicks) > 360000)	||
363 		 ( nTicks < nCacheTicks ) // handle overflow
364 		 )
365 	{
366 		nTime = time( 0 );
367 		localtime_r( &nTime, &aTM );
368 		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 		nUTC = nLocalTime - aTM.tm_gmtoff;
376 #else
377  		gmtime_r( &nTime, &aTM );
378  		nUTC = mktime( &aTM );
379 #endif
380  		nCacheTicks = nTicks;
381  		nCacheSecOffset = (nLocalTime-nUTC) / 60;
382 	}
383 
384 	nTempTime = (short)Abs( nCacheSecOffset );
385 	Time aTime( 0, (sal_uInt16)nTempTime );
386 	if ( nCacheSecOffset < 0 )
387 		aTime = -aTime;
388 	return aTime;
389 #endif
390 }
391 
392 
393 // -----------------------------------------------------------------------
394 
395 sal_uIntPtr Time::GetSystemTicks()
396 {
397 #if defined WNT
398 	return (sal_uIntPtr)GetTickCount();
399 #elif defined( OS2 )
400 	sal_uIntPtr nClock;
401 	DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) );
402 	return (sal_uIntPtr)nClock;
403 #else
404 	timeval tv;
405 	gettimeofday (&tv, 0);
406 
407 	double fTicks = tv.tv_sec;
408 	fTicks *= 1000;
409 	fTicks += ((tv.tv_usec + 500) / 1000);
410 
411 	fTicks = fmod (fTicks, double(ULONG_MAX));
412 	return sal_uIntPtr(fTicks);
413 #endif
414 }
415 
416 // -----------------------------------------------------------------------
417 
418 sal_uIntPtr Time::GetProcessTicks()
419 {
420 #if defined WNT
421 	return (sal_uIntPtr)GetTickCount();
422 #elif defined( OS2 )
423 	sal_uIntPtr nClock;
424 	DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) );
425 	return (sal_uIntPtr)nClock;
426 #else
427 	static sal_uIntPtr	nImplTicksPerSecond = 0;
428 	static double	dImplTicksPerSecond;
429 	static double	dImplTicksULONGMAX;
430 	sal_uIntPtr			nTicks = (sal_uIntPtr)clock();
431 
432 	if ( !nImplTicksPerSecond )
433 	{
434 		nImplTicksPerSecond = CLOCKS_PER_SEC;
435 		dImplTicksPerSecond = nImplTicksPerSecond;
436 		dImplTicksULONGMAX	= (double)(sal_uIntPtr)ULONG_MAX;
437 	}
438 
439 	double fTicks = nTicks;
440 	fTicks *= 1000;
441 	fTicks /= dImplTicksPerSecond;
442 	fTicks = fmod (fTicks, dImplTicksULONGMAX);
443 	return (sal_uIntPtr)fTicks;
444 #endif
445 }
446