Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / basic / source / sbx / sbxdate.cxx
blobe716b57eeac8c2aadf24511f53968b8f1573e812
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/svapp.hxx>
21 #include <vcl/settings.hxx>
22 #include <svl/zforlist.hxx>
23 #include <tools/color.hxx>
24 #include <i18nlangtag/lang.h>
25 #include <basic/sberrors.hxx>
26 #include "sbxconv.hxx"
27 #include <runtime.hxx>
28 #include <sbintern.hxx>
29 #include <math.h>
30 #include <memory>
31 #include <config_features.h>
34 double ImpGetDate( const SbxValues* p )
36 double nRes;
37 SbxValue* pVal;
39 switch( +p->eType )
41 case SbxNULL:
42 SbxBase::SetError( ERRCODE_BASIC_CONVERSION );
43 [[fallthrough]];
44 case SbxEMPTY:
45 nRes = 0;
46 break;
47 case SbxCHAR:
48 nRes = p->nChar;
49 break;
50 case SbxBYTE:
51 nRes = p->nByte;
52 break;
53 case SbxINTEGER:
54 case SbxBOOL:
55 nRes = p->nInteger;
56 break;
57 case SbxERROR:
58 case SbxUSHORT:
59 nRes = p->nUShort;
60 break;
61 case SbxLONG:
62 nRes = static_cast<double>(p->nLong);
63 break;
64 case SbxULONG:
65 nRes = static_cast<double>(p->nULong);
66 break;
67 case SbxSINGLE:
68 nRes = p->nSingle;
69 break;
70 case SbxDATE:
71 case SbxDOUBLE:
72 nRes = p->nDouble;
73 break;
74 case SbxCURRENCY:
75 nRes = ImpCurrencyToDouble( p->nInt64 );
76 break;
77 case SbxSALINT64:
78 nRes = static_cast< double >(p->nInt64);
79 break;
80 case SbxSALUINT64:
81 nRes = ImpSalUInt64ToDouble( p->uInt64 );
82 break;
83 case SbxDECIMAL:
84 case SbxBYREF | SbxDECIMAL:
85 if( p->pDecimal )
87 p->pDecimal->getDouble( nRes );
89 else
91 nRes = 0.0;
93 break;
94 case SbxBYREF | SbxSTRING:
95 case SbxSTRING:
96 case SbxLPSTR:
97 #if HAVE_FEATURE_SCRIPTING
98 if( !p->pOUString )
100 nRes = 0;
102 else
104 LanguageType eLangType = Application::GetSettings().GetLanguageTag().getLanguageType();
105 std::shared_ptr<SvNumberFormatter> pFormatter;
106 if (GetSbData()->pInst)
108 pFormatter = GetSbData()->pInst->GetNumberFormatter();
110 else
112 sal_uInt32 nDummy;
113 pFormatter = SbiInstance::PrepareNumberFormatter( nDummy, nDummy, nDummy );
116 sal_uInt32 nIndex;
117 sal_Int32 nCheckPos = 0;
118 SvNumFormatType nType = SvNumFormatType::DEFINED | SvNumFormatType::DATE | SvNumFormatType::TIME | SvNumFormatType::CURRENCY
119 | SvNumFormatType::NUMBER | SvNumFormatType::SCIENTIFIC | SvNumFormatType::FRACTION;
121 // Default templates of the formatter have only two-digit
122 // date. Therefore register an own format.
124 // HACK, because the number formatter in PutandConvertEntry replace the wildcard
125 // for month, day, year not according to the configuration.
126 // Problem: Print Year(Date) under Engl. OS
127 // quod vide basic/source/runtime/runtime.cxx
129 SvtSysLocale aSysLocale;
130 DateOrder eDate = aSysLocale.GetLocaleData().getDateOrder();
131 OUString aDateStr;
132 switch( eDate )
134 default:
135 case DateOrder::MDY: aDateStr = "MM/DD/YYYY"; break;
136 case DateOrder::DMY: aDateStr = "DD/MM/YYYY"; break;
137 case DateOrder::YMD: aDateStr = "YYYY/MM/DD"; break;
140 OUString aStr = aDateStr + " HH:MM:SS";
142 pFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
143 nIndex, LANGUAGE_ENGLISH_US, eLangType, true);
144 bool bSuccess = pFormatter->IsNumberFormat( *p->pOUString, nIndex, nRes );
145 if ( bSuccess )
147 SvNumFormatType nType_ = pFormatter->GetType( nIndex );
148 if(!(nType_ & ( SvNumFormatType::DATETIME | SvNumFormatType::DATE |
149 SvNumFormatType::TIME | SvNumFormatType::DEFINED )))
151 bSuccess = false;
155 if ( !bSuccess )
157 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); nRes = 0;
160 #else
161 nRes = 0;
162 #endif
163 break;
164 case SbxOBJECT:
165 pVal = dynamic_cast<SbxValue*>( p->pObj );
166 if( pVal )
168 nRes = pVal->GetDate();
170 else
172 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); nRes = 0;
174 break;
175 case SbxBYREF | SbxCHAR:
176 nRes = *p->pChar;
177 break;
178 case SbxBYREF | SbxBYTE:
179 nRes = *p->pByte;
180 break;
181 case SbxBYREF | SbxINTEGER:
182 case SbxBYREF | SbxBOOL:
183 nRes = *p->pInteger;
184 break;
185 case SbxBYREF | SbxLONG:
186 nRes = *p->pLong;
187 break;
188 case SbxBYREF | SbxULONG:
189 nRes = *p->pULong;
190 break;
191 case SbxBYREF | SbxERROR:
192 case SbxBYREF | SbxUSHORT:
193 nRes = *p->pUShort;
194 break;
195 case SbxBYREF | SbxSINGLE:
196 nRes = *p->pSingle;
197 break;
198 case SbxBYREF | SbxDATE:
199 case SbxBYREF | SbxDOUBLE:
200 nRes = *p->pDouble;
201 break;
202 case SbxBYREF | SbxCURRENCY:
203 nRes = ImpCurrencyToDouble( *p->pnInt64 );
204 break;
205 case SbxBYREF | SbxSALINT64:
206 nRes = static_cast< double >(*p->pnInt64);
207 break;
208 case SbxBYREF | SbxSALUINT64:
209 nRes = ImpSalUInt64ToDouble( *p->puInt64 );
210 break;
211 default:
212 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); nRes = 0;
213 break;
215 return nRes;
218 void ImpPutDate( SbxValues* p, double n )
220 SbxValues aTmp;
221 SbxDecimal* pDec;
222 SbxValue* pVal;
224 start:
225 switch( +p->eType )
227 case SbxDATE:
228 case SbxDOUBLE:
229 p->nDouble = n;
230 break;
231 // from here will be tested
232 case SbxCHAR:
233 aTmp.pChar = &p->nChar;
234 goto direct;
235 case SbxBYTE:
236 aTmp.pByte = &p->nByte;
237 goto direct;
238 case SbxINTEGER:
239 case SbxBOOL:
240 aTmp.pInteger = &p->nInteger;
241 goto direct;
242 case SbxLONG:
243 aTmp.pLong = &p->nLong;
244 goto direct;
245 case SbxULONG:
246 aTmp.pULong = &p->nULong;
247 goto direct;
248 case SbxERROR:
249 case SbxUSHORT:
250 aTmp.pUShort = &p->nUShort;
251 goto direct;
252 case SbxSINGLE:
253 aTmp.pSingle = &p->nSingle;
254 goto direct;
255 case SbxCURRENCY:
256 case SbxSALINT64:
257 aTmp.pnInt64 = &p->nInt64;
258 goto direct;
259 case SbxSALUINT64:
260 aTmp.puInt64 = &p->uInt64;
261 goto direct;
262 case SbxDECIMAL:
263 case SbxBYREF | SbxDECIMAL:
264 pDec = ImpCreateDecimal( p );
265 if( !pDec->setDouble( n ) )
267 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW );
269 break;
270 direct:
271 aTmp.eType = SbxDataType( p->eType | SbxBYREF );
272 p = &aTmp; goto start;
274 case SbxBYREF | SbxSTRING:
275 case SbxSTRING:
276 case SbxLPSTR:
278 #if HAVE_FEATURE_SCRIPTING
279 if( !p->pOUString )
281 p->pOUString = new OUString;
283 Color* pColor;
285 LanguageType eLangType = Application::GetSettings().GetLanguageTag().getLanguageType();
286 std::shared_ptr<SvNumberFormatter> pFormatter;
287 if (GetSbData()->pInst)
289 pFormatter = GetSbData()->pInst->GetNumberFormatter();
291 else
293 sal_uInt32 nDummy;
294 pFormatter = SbiInstance::PrepareNumberFormatter( nDummy, nDummy, nDummy );
297 sal_uInt32 nIndex;
298 sal_Int32 nCheckPos = 0;
299 SvNumFormatType nType;
301 SvtSysLocale aSysLocale;
302 DateOrder eDate = aSysLocale.GetLocaleData().getDateOrder();
303 OUString aStr;
304 // if the whole-number part is 0, we want no year!
305 if( n <= -1.0 || n >= 1.0 )
307 // Time only if != 00:00:00
308 if( rtl::math::approxEqual(floor( n ), n) )
310 switch( eDate )
312 default:
313 case DateOrder::MDY: aStr = "MM/DD/YYYY"; break;
314 case DateOrder::DMY: aStr = "DD/MM/YYYY"; break;
315 case DateOrder::YMD: aStr = "YYYY/MM/DD"; break;
318 else
320 switch( eDate )
322 default:
323 case DateOrder::MDY: aStr = "MM/DD/YYYY HH:MM:SS"; break;
324 case DateOrder::DMY: aStr = "DD/MM/YYYY HH:MM:SS"; break;
325 case DateOrder::YMD: aStr = "YYYY/MM/DD HH:MM:SS"; break;
329 else
331 aStr = "HH:MM:SS";
333 pFormatter->PutandConvertEntry( aStr,
334 nCheckPos,
335 nType,
336 nIndex,
337 LANGUAGE_ENGLISH_US,
338 eLangType, true);
339 pFormatter->GetOutputString( n, nIndex, *p->pOUString, &pColor );
340 #endif
341 break;
343 case SbxOBJECT:
344 pVal = dynamic_cast<SbxValue*>( p->pObj );
345 if( pVal )
347 pVal->PutDate( n );
349 else
351 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT );
353 break;
354 case SbxBYREF | SbxCHAR:
355 if( n > SbxMAXCHAR )
357 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXCHAR;
359 else if( n < SbxMINCHAR )
361 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINCHAR;
363 *p->pChar = static_cast<sal_Unicode>(n);
364 break;
365 case SbxBYREF | SbxBYTE:
366 if( n > SbxMAXBYTE )
368 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXBYTE;
370 else if( n < 0 )
372 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0;
374 *p->pByte = static_cast<sal_uInt8>(n);
375 break;
376 case SbxBYREF | SbxINTEGER:
377 case SbxBYREF | SbxBOOL:
378 if( n > SbxMAXINT )
380 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXINT;
382 else if( n < SbxMININT )
384 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMININT;
386 *p->pInteger = static_cast<sal_Int16>(n);
387 break;
388 case SbxBYREF | SbxERROR:
389 case SbxBYREF | SbxUSHORT:
390 if( n > SbxMAXUINT )
392 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXUINT;
394 else if( n < 0 )
396 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0;
398 *p->pUShort = static_cast<sal_uInt16>(n);
399 break;
400 case SbxBYREF | SbxLONG:
401 if( n > SbxMAXLNG )
403 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXLNG;
405 else if( n < SbxMINLNG )
407 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINLNG;
409 *p->pLong = static_cast<sal_Int32>(n);
410 break;
411 case SbxBYREF | SbxULONG:
412 if( n > SbxMAXULNG )
414 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXULNG;
416 else if( n < 0 )
418 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0;
420 *p->pULong = static_cast<sal_uInt32>(n);
421 break;
422 case SbxBYREF | SbxSINGLE:
423 if( n > SbxMAXSNG )
425 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXSNG;
427 else if( n < SbxMINSNG )
429 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINSNG;
431 *p->pSingle = static_cast<float>(n);
432 break;
433 case SbxBYREF | SbxSALINT64:
434 *p->pnInt64 = ImpDoubleToSalInt64( n );
435 break;
436 case SbxBYREF | SbxSALUINT64:
437 *p->puInt64 = ImpDoubleToSalUInt64( n );
438 break;
439 case SbxBYREF | SbxDATE:
440 case SbxBYREF | SbxDOUBLE:
441 *p->pDouble = n;
442 break;
443 case SbxBYREF | SbxCURRENCY:
444 if( n > SbxMAXCURR )
446 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXCURR;
448 else if( n < SbxMINCURR )
450 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINCURR;
452 *p->pnInt64 = ImpDoubleToCurrency( n );
453 break;
454 default:
455 SbxBase::SetError( ERRCODE_BASIC_CONVERSION );
456 break;
460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */