xref: /trunk/main/basic/source/sbx/sbxdate.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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