xref: /aoo42x/main/basic/source/sbx/sbxdate.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_basic.hxx"
30 #include <vcl/svapp.hxx>
31 #include <svl/zforlist.hxx>
32 #include <tools/errcode.hxx>
33 #include <tools/color.hxx>
34 #include <i18npool/lang.h>
35 #include <basic/sbx.hxx>
36 #include "sbxconv.hxx"
37 #include "math.h"
38 #include <comphelper/processfactory.hxx>
39 
40 
41 double ImpGetDate( const SbxValues* p )
42 {
43 	double nRes;
44 	switch( +p->eType )
45 	{
46 		case SbxNULL:
47 			SbxBase::SetError( SbxERR_CONVERSION );
48 		case SbxEMPTY:
49 			nRes = 0; break;
50 		case SbxCHAR:
51 			nRes = p->nChar; break;
52 		case SbxBYTE:
53 			nRes = p->nByte; break;
54 		case SbxINTEGER:
55 		case SbxBOOL:
56 			nRes = p->nInteger; break;
57 		case SbxERROR:
58 		case SbxUSHORT:
59 			nRes = p->nUShort; break;
60 		case SbxLONG:
61 			nRes = (double) p->nLong; break;
62 		case SbxULONG:
63 			nRes = (double) p->nULong; break;
64 		case SbxSINGLE:
65 			nRes = p->nSingle; break;
66 		case SbxDATE:
67 		case SbxDOUBLE:
68 			nRes = p->nDouble; break;
69 		case SbxULONG64:
70 			nRes = ImpUINT64ToDouble( p->nULong64 ); break;
71 		case SbxLONG64:
72 			nRes = ImpINT64ToDouble( p->nLong64 ); break;
73 		case SbxCURRENCY:
74 			nRes = ImpCurrencyToDouble( p->nLong64 ); break;
75 		case SbxSALINT64:
76             nRes = static_cast< double >(p->nInt64); break;
77 		case SbxSALUINT64:
78             nRes = ImpSalUInt64ToDouble( p->uInt64 ); break;
79 		case SbxDECIMAL:
80 		case SbxBYREF | SbxDECIMAL:
81 			if( p->pDecimal )
82 				p->pDecimal->getDouble( nRes );
83 			else
84 				nRes = 0.0;
85 			break;
86 		case SbxBYREF | SbxSTRING:
87 		case SbxSTRING:
88 		case SbxLPSTR:
89 			if( !p->pOUString )
90 				nRes = 0;
91 			else
92 			{
93                 LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
94 
95 				SvNumberFormatter* pFormatter;
96 				com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
97 					xFactory = comphelper::getProcessServiceFactory();
98 				pFormatter = new SvNumberFormatter( xFactory, eLangType );
99 
100 				sal_uInt32 nIndex;
101 				xub_StrLen nCheckPos = 0;
102 				short nType = 127;
103 
104 				// Standard-Vorlagen des Formatters haben nur zweistellige
105 				// Jahreszahl. Deshalb eigenes Format registrieren
106 
107 				// HACK, da der Numberformatter in PutandConvertEntry die Platzhalter
108 				// fuer Monat, Tag, Jahr nicht entsprechend der Systemeinstellung
109 				// austauscht. Problem: Print Year(Date) unter engl. BS
110 				// siehe auch basic\source\runtime\runtime.cxx
111 
112                 SvtSysLocale aSysLocale;
113                 DateFormat eDate = aSysLocale.GetLocaleData().getDateFormat();
114 				String aDateStr;
115 				switch( eDate )
116 				{
117 					case MDY: aDateStr.AssignAscii( "MM.TT.JJJJ" ); break;
118 					case DMY: aDateStr.AssignAscii( "TT.MM.JJJJ" ); break;
119 					case YMD: aDateStr.AssignAscii( "JJJJ.MM.TT" ); break;
120 					default:  aDateStr.AssignAscii( "MM.TT.JJJJ" );
121 				}
122 
123 				String aStr( aDateStr );
124 				aStr.AppendAscii( " HH:MM:SS" );
125 
126 				pFormatter->PutandConvertEntry( aStr, nCheckPos,	nType,
127 					nIndex, LANGUAGE_GERMAN, eLangType );
128 				sal_Bool bSuccess = pFormatter->IsNumberFormat( *p->pOUString, nIndex, nRes );
129 				if ( bSuccess )
130 				{
131 					short nType_ = pFormatter->GetType( nIndex );
132 					if(!(nType_ & (	NUMBERFORMAT_DATETIME | NUMBERFORMAT_DATE |
133 									NUMBERFORMAT_TIME | NUMBERFORMAT_DEFINED )))
134 						bSuccess = sal_False;
135 				}
136 
137 				if ( !bSuccess )
138 				{
139 					SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
140 				}
141 
142 				delete pFormatter;
143 			}
144 			break;
145 		case SbxOBJECT:
146 		{
147 			SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
148 			if( pVal )
149 				nRes = pVal->GetDate();
150 			else
151 			{
152 				SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
153 			}
154 			break;
155 		}
156 
157 		case SbxBYREF | SbxCHAR:
158 			nRes = *p->pChar; break;
159 		case SbxBYREF | SbxBYTE:
160 			nRes = *p->pByte; break;
161 		case SbxBYREF | SbxINTEGER:
162 		case SbxBYREF | SbxBOOL:
163 			nRes = *p->pInteger; break;
164 		case SbxBYREF | SbxLONG:
165 			nRes = *p->pLong; break;
166 		case SbxBYREF | SbxULONG:
167 			nRes = *p->pULong; break;
168 		case SbxBYREF | SbxERROR:
169 		case SbxBYREF | SbxUSHORT:
170 			nRes = *p->pUShort; break;
171 		case SbxBYREF | SbxSINGLE:
172 			nRes = *p->pSingle; break;
173 		case SbxBYREF | SbxDATE:
174 		case SbxBYREF | SbxDOUBLE:
175 			nRes = *p->pDouble; break;
176 		case SbxBYREF | SbxULONG64:
177 			nRes = ImpUINT64ToDouble( *p->pULong64 ); break;
178 		case SbxBYREF | SbxLONG64:
179 			nRes = ImpINT64ToDouble( *p->pLong64 ); break;
180 		case SbxBYREF | SbxCURRENCY:
181 			nRes = ImpCurrencyToDouble( *p->pLong64 ); break;
182 		case SbxBYREF | SbxSALINT64:
183             nRes = static_cast< double >(*p->pnInt64); break;
184 		case SbxBYREF | SbxSALUINT64:
185             nRes = ImpSalUInt64ToDouble( *p->puInt64 ); break;
186 
187 		default:
188 			SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
189 	}
190 	return nRes;
191 }
192 
193 void ImpPutDate( SbxValues* p, double n )
194 {
195 	SbxValues aTmp;
196 
197 start:
198 	switch( +p->eType )
199 	{
200 		case SbxDATE:
201 		case SbxDOUBLE:
202 			p->nDouble = n; break;
203 
204 		// ab hier wird getestet
205 		case SbxCHAR:
206 			aTmp.pChar = &p->nChar; goto direct;
207 		case SbxBYTE:
208 			aTmp.pByte = &p->nByte; goto direct;
209 		case SbxINTEGER:
210 		case SbxBOOL:
211 			aTmp.pInteger = &p->nInteger; goto direct;
212 		case SbxLONG:
213 			aTmp.pLong = &p->nLong; goto direct;
214 		case SbxULONG:
215 			aTmp.pULong = &p->nULong; goto direct;
216 		case SbxERROR:
217 		case SbxUSHORT:
218 			aTmp.pUShort = &p->nUShort; goto direct;
219 		case SbxSINGLE:
220 			aTmp.pSingle = &p->nSingle; goto direct;
221 		case SbxULONG64:
222 			aTmp.pULong64 = &p->nULong64; goto direct;
223 		case SbxLONG64:
224 		case SbxCURRENCY:
225 			aTmp.pLong64 = &p->nLong64; goto direct;
226 		case SbxSALINT64:
227 			aTmp.pnInt64 = &p->nInt64; goto direct;
228 		case SbxSALUINT64:
229 			aTmp.puInt64 = &p->uInt64; goto direct;
230 		case SbxDECIMAL:
231 		case SbxBYREF | SbxDECIMAL:
232 			{
233 			SbxDecimal* pDec = ImpCreateDecimal( p );
234 			if( !pDec->setDouble( n ) )
235 				SbxBase::SetError( SbxERR_OVERFLOW );
236 			break;
237 			}
238 		direct:
239 			aTmp.eType = SbxDataType( p->eType | SbxBYREF );
240 			p = &aTmp; goto start;
241 
242 		case SbxBYREF | SbxSTRING:
243 		case SbxSTRING:
244 		case SbxLPSTR:
245 		{
246 			if( !p->pOUString )
247 				p->pOUString = new ::rtl::OUString;
248 			Color* pColor;
249 
250             LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
251 			SvNumberFormatter* pFormatter;
252 			com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
253 				xFactory = comphelper::getProcessServiceFactory();
254 			pFormatter = new SvNumberFormatter( xFactory, eLangType );
255 
256 			sal_uInt32 nIndex;
257 			xub_StrLen nCheckPos = 0;
258 			short nType;
259 
260             SvtSysLocale aSysLocale;
261             DateFormat eDate = aSysLocale.GetLocaleData().getDateFormat();
262 			String aStr;
263 			// ist der ganzzahlige Teil 0, wollen wir kein Jahr!
264 			if( n <= -1.0 || n >= 1.0 )
265 			{
266 				// Time only if != 00:00:00
267 				if( floor( n ) == n )
268                 {
269 				    switch( eDate )
270 				    {
271 					    case MDY: aStr.AssignAscii( "MM.TT.JJJJ" ); break;
272 					    case DMY: aStr.AssignAscii( "TT.MM.JJJJ" ); break;
273 					    case YMD: aStr.AssignAscii( "JJJJ.MM.TT" ); break;
274 					    default:  aStr.AssignAscii( "MM.TT.JJJJ" );
275 				    }
276                 }
277 				else
278                 {
279 				    switch( eDate )
280 				    {
281 					    case MDY: aStr.AssignAscii( "MM.TT.JJJJ HH:MM:SS" ); break;
282 					    case DMY: aStr.AssignAscii( "TT.MM.JJJJ HH:MM:SS" ); break;
283 					    case YMD: aStr.AssignAscii( "JJJJ.MM.TT HH:MM:SS" ); break;
284 					    default:  aStr.AssignAscii( "MM.TT.JJJJ HH:MM:SS" );
285 				    }
286                 }
287 			}
288 			else
289 				aStr.AppendAscii( "HH:MM:SS" );
290 
291 			pFormatter->PutandConvertEntry( aStr,
292 				nCheckPos,
293 				nType,
294 				nIndex,
295 				LANGUAGE_GERMAN,
296 				eLangType );
297             String aTmpString;
298 			pFormatter->GetOutputString( n, nIndex, aTmpString, &pColor );
299             *p->pOUString = aTmpString;
300 			delete pFormatter;
301 			break;
302 		}
303 		case SbxOBJECT:
304 		{
305 			SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
306 			if( pVal )
307 				pVal->PutDate( n );
308 			else
309 				SbxBase::SetError( SbxERR_NO_OBJECT );
310 			break;
311 		}
312 		case SbxBYREF | SbxCHAR:
313 			if( n > SbxMAXCHAR )
314 			{
315 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR;
316 			}
317 			else if( n < SbxMINCHAR )
318 			{
319 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR;
320 			}
321 			*p->pChar = (xub_Unicode) n; break;
322 		case SbxBYREF | SbxBYTE:
323 			if( n > SbxMAXBYTE )
324 			{
325 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
326 			}
327 			else if( n < 0 )
328 			{
329 				SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
330 			}
331 			*p->pByte = (sal_uInt8) n; break;
332 		case SbxBYREF | SbxINTEGER:
333 		case SbxBYREF | SbxBOOL:
334 			if( n > SbxMAXINT )
335 			{
336 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
337 			}
338 			else if( n < SbxMININT )
339 			{
340 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT;
341 			}
342 			*p->pInteger = (sal_Int16) n; break;
343 		case SbxBYREF | SbxERROR:
344 		case SbxBYREF | SbxUSHORT:
345 			if( n > SbxMAXUINT )
346 			{
347 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
348 			}
349 			else if( n < 0 )
350 			{
351 				SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
352 			}
353 			*p->pUShort = (sal_uInt16) n; break;
354 		case SbxBYREF | SbxLONG:
355 			if( n > SbxMAXLNG )
356 			{
357 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG;
358 			}
359 			else if( n < SbxMINLNG )
360 			{
361 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINLNG;
362 			}
363 			*p->pLong = (sal_Int32) n; break;
364 		case SbxBYREF | SbxULONG:
365 			if( n > SbxMAXULNG )
366 			{
367 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG;
368 			}
369 			else if( n < 0 )
370 			{
371 				SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
372 			}
373 			*p->pULong = (sal_uInt32) n; break;
374 		case SbxBYREF | SbxSINGLE:
375 			if( n > SbxMAXSNG )
376 			{
377 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXSNG;
378 			}
379 			else if( n < SbxMINSNG )
380 			{
381 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINSNG;
382 			}
383 			*p->pSingle = (float) n; break;
384 		case SbxBYREF | SbxSALINT64:
385             *p->pnInt64 = ImpDoubleToSalInt64( n ); break;
386 		case SbxBYREF | SbxSALUINT64:
387 			*p->puInt64 = ImpDoubleToSalUInt64( n ); break;
388 		case SbxBYREF | SbxDATE:
389 		case SbxBYREF | SbxDOUBLE:
390 			*p->pDouble = (double) n; break;
391 		case SbxBYREF | SbxCURRENCY:
392 			if( n > SbxMAXCURR )
393 			{
394 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCURR;
395 			}
396 			else if( n < SbxMINCURR )
397 			{
398 				SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCURR;
399 			}
400 			*p->pLong64 = ImpDoubleToCurrency( n ); break;
401 
402 		default:
403 			SbxBase::SetError( SbxERR_CONVERSION );
404 	}
405 }
406 
407