nss: upgrade to release 3.73
[LibreOffice.git] / basic / source / sbx / sbxdate.cxx
blob07947bffe3137b50b10d5b032b4658a62fbc964f
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 <rtl/math.hxx>
21 #include <vcl/svapp.hxx>
22 #include <vcl/settings.hxx>
23 #include <svl/zforlist.hxx>
24 #include <tools/color.hxx>
25 #include <i18nlangtag/lang.h>
26 #include <basic/sberrors.hxx>
27 #include "sbxconv.hxx"
28 #include <runtime.hxx>
29 #include <sbintern.hxx>
30 #include <math.h>
31 #include <memory>
32 #include <config_features.h>
35 double ImpGetDate( const SbxValues* p )
37 double nRes;
38 SbxValue* pVal;
40 switch( +p->eType )
42 case SbxNULL:
43 SbxBase::SetError( ERRCODE_BASIC_CONVERSION );
44 [[fallthrough]];
45 case SbxEMPTY:
46 nRes = 0;
47 break;
48 case SbxCHAR:
49 nRes = p->nChar;
50 break;
51 case SbxBYTE:
52 nRes = p->nByte;
53 break;
54 case SbxINTEGER:
55 case SbxBOOL:
56 nRes = p->nInteger;
57 break;
58 case SbxERROR:
59 case SbxUSHORT:
60 nRes = p->nUShort;
61 break;
62 case SbxLONG:
63 nRes = static_cast<double>(p->nLong);
64 break;
65 case SbxULONG:
66 nRes = static_cast<double>(p->nULong);
67 break;
68 case SbxSINGLE:
69 nRes = p->nSingle;
70 break;
71 case SbxDATE:
72 case SbxDOUBLE:
73 nRes = p->nDouble;
74 break;
75 case SbxCURRENCY:
76 nRes = ImpCurrencyToDouble( p->nInt64 );
77 break;
78 case SbxSALINT64:
79 nRes = static_cast< double >(p->nInt64);
80 break;
81 case SbxSALUINT64:
82 nRes = ImpSalUInt64ToDouble( p->uInt64 );
83 break;
84 case SbxDECIMAL:
85 case SbxBYREF | SbxDECIMAL:
86 if( p->pDecimal )
88 p->pDecimal->getDouble( nRes );
90 else
92 nRes = 0.0;
94 break;
95 case SbxBYREF | SbxSTRING:
96 case SbxSTRING:
97 case SbxLPSTR:
98 #if HAVE_FEATURE_SCRIPTING
99 if( !p->pOUString )
101 nRes = 0;
103 else
105 LanguageType eLangType = Application::GetSettings().GetLanguageTag().getLanguageType();
106 std::shared_ptr<SvNumberFormatter> pFormatter;
107 if (GetSbData()->pInst)
109 pFormatter = GetSbData()->pInst->GetNumberFormatter();
111 else
113 sal_uInt32 nDummy;
114 pFormatter = SbiInstance::PrepareNumberFormatter( nDummy, nDummy, nDummy );
117 sal_uInt32 nIndex;
118 sal_Int32 nCheckPos = 0;
119 SvNumFormatType nType = SvNumFormatType::DEFINED | SvNumFormatType::DATE | SvNumFormatType::TIME | SvNumFormatType::CURRENCY
120 | SvNumFormatType::NUMBER | SvNumFormatType::SCIENTIFIC | SvNumFormatType::FRACTION;
122 // Default templates of the formatter have only two-digit
123 // date. Therefore register an own format.
125 // HACK, because the number formatter in PutandConvertEntry replace the wildcard
126 // for month, day, year not according to the configuration.
127 // Problem: Print Year(Date) under Engl. OS
128 // quod vide basic/source/runtime/runtime.cxx
130 SvtSysLocale aSysLocale;
131 DateOrder eDate = aSysLocale.GetLocaleData().getDateOrder();
132 OUString aDateStr;
133 switch( eDate )
135 default:
136 case DateOrder::MDY: aDateStr = "MM/DD/YYYY"; break;
137 case DateOrder::DMY: aDateStr = "DD/MM/YYYY"; break;
138 case DateOrder::YMD: aDateStr = "YYYY/MM/DD"; break;
141 OUString aStr = aDateStr + " HH:MM:SS";
143 pFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
144 nIndex, LANGUAGE_ENGLISH_US, eLangType, true);
145 bool bSuccess = pFormatter->IsNumberFormat( *p->pOUString, nIndex, nRes );
146 if ( bSuccess )
148 SvNumFormatType nType_ = pFormatter->GetType( nIndex );
149 if(!(nType_ & ( SvNumFormatType::DATETIME | SvNumFormatType::DATE |
150 SvNumFormatType::TIME | SvNumFormatType::DEFINED )))
152 bSuccess = false;
156 if ( !bSuccess )
158 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); nRes = 0;
161 #else
162 nRes = 0;
163 #endif
164 break;
165 case SbxOBJECT:
166 pVal = dynamic_cast<SbxValue*>( p->pObj );
167 if( pVal )
169 nRes = pVal->GetDate();
171 else
173 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT ); nRes = 0;
175 break;
176 case SbxBYREF | SbxCHAR:
177 nRes = *p->pChar;
178 break;
179 case SbxBYREF | SbxBYTE:
180 nRes = *p->pByte;
181 break;
182 case SbxBYREF | SbxINTEGER:
183 case SbxBYREF | SbxBOOL:
184 nRes = *p->pInteger;
185 break;
186 case SbxBYREF | SbxLONG:
187 nRes = *p->pLong;
188 break;
189 case SbxBYREF | SbxULONG:
190 nRes = *p->pULong;
191 break;
192 case SbxBYREF | SbxERROR:
193 case SbxBYREF | SbxUSHORT:
194 nRes = *p->pUShort;
195 break;
196 case SbxBYREF | SbxSINGLE:
197 nRes = *p->pSingle;
198 break;
199 case SbxBYREF | SbxDATE:
200 case SbxBYREF | SbxDOUBLE:
201 nRes = *p->pDouble;
202 break;
203 case SbxBYREF | SbxCURRENCY:
204 nRes = ImpCurrencyToDouble( *p->pnInt64 );
205 break;
206 case SbxBYREF | SbxSALINT64:
207 nRes = static_cast< double >(*p->pnInt64);
208 break;
209 case SbxBYREF | SbxSALUINT64:
210 nRes = ImpSalUInt64ToDouble( *p->puInt64 );
211 break;
212 default:
213 SbxBase::SetError( ERRCODE_BASIC_CONVERSION ); nRes = 0;
214 break;
216 return nRes;
219 void ImpPutDate( SbxValues* p, double n )
221 SbxValues aTmp;
222 SbxDecimal* pDec;
223 SbxValue* pVal;
225 start:
226 switch( +p->eType )
228 case SbxDATE:
229 case SbxDOUBLE:
230 p->nDouble = n;
231 break;
232 // from here will be tested
233 case SbxCHAR:
234 aTmp.pChar = &p->nChar;
235 goto direct;
236 case SbxBYTE:
237 aTmp.pByte = &p->nByte;
238 goto direct;
239 case SbxINTEGER:
240 case SbxBOOL:
241 aTmp.pInteger = &p->nInteger;
242 goto direct;
243 case SbxLONG:
244 aTmp.pLong = &p->nLong;
245 goto direct;
246 case SbxULONG:
247 aTmp.pULong = &p->nULong;
248 goto direct;
249 case SbxERROR:
250 case SbxUSHORT:
251 aTmp.pUShort = &p->nUShort;
252 goto direct;
253 case SbxSINGLE:
254 aTmp.pSingle = &p->nSingle;
255 goto direct;
256 case SbxCURRENCY:
257 case SbxSALINT64:
258 aTmp.pnInt64 = &p->nInt64;
259 goto direct;
260 case SbxSALUINT64:
261 aTmp.puInt64 = &p->uInt64;
262 goto direct;
263 case SbxDECIMAL:
264 case SbxBYREF | SbxDECIMAL:
265 pDec = ImpCreateDecimal( p );
266 if( !pDec->setDouble( n ) )
268 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW );
270 break;
271 direct:
272 aTmp.eType = SbxDataType( p->eType | SbxBYREF );
273 p = &aTmp; goto start;
275 case SbxBYREF | SbxSTRING:
276 case SbxSTRING:
277 case SbxLPSTR:
279 #if HAVE_FEATURE_SCRIPTING
280 if( !p->pOUString )
282 p->pOUString = new OUString;
284 const Color* pColor;
286 LanguageType eLangType = Application::GetSettings().GetLanguageTag().getLanguageType();
287 std::shared_ptr<SvNumberFormatter> pFormatter;
288 if (GetSbData()->pInst)
290 pFormatter = GetSbData()->pInst->GetNumberFormatter();
292 else
294 sal_uInt32 nDummy;
295 pFormatter = SbiInstance::PrepareNumberFormatter( nDummy, nDummy, nDummy );
298 sal_uInt32 nIndex;
299 sal_Int32 nCheckPos = 0;
300 SvNumFormatType nType;
302 SvtSysLocale aSysLocale;
303 DateOrder eDate = aSysLocale.GetLocaleData().getDateOrder();
304 OUString aStr;
305 // if the whole-number part is 0, we want no year!
306 if( n <= -1.0 || n >= 1.0 )
308 // Time only if != 00:00:00
309 if( rtl::math::approxEqual(floor( n ), n) )
311 switch( eDate )
313 default:
314 case DateOrder::MDY: aStr = "MM/DD/YYYY"; break;
315 case DateOrder::DMY: aStr = "DD/MM/YYYY"; break;
316 case DateOrder::YMD: aStr = "YYYY/MM/DD"; break;
319 else
321 switch( eDate )
323 default:
324 case DateOrder::MDY: aStr = "MM/DD/YYYY HH:MM:SS"; break;
325 case DateOrder::DMY: aStr = "DD/MM/YYYY HH:MM:SS"; break;
326 case DateOrder::YMD: aStr = "YYYY/MM/DD HH:MM:SS"; break;
330 else
332 aStr = "HH:MM:SS";
334 pFormatter->PutandConvertEntry( aStr,
335 nCheckPos,
336 nType,
337 nIndex,
338 LANGUAGE_ENGLISH_US,
339 eLangType, true);
340 pFormatter->GetOutputString( n, nIndex, *p->pOUString, &pColor );
341 #endif
342 break;
344 case SbxOBJECT:
345 pVal = dynamic_cast<SbxValue*>( p->pObj );
346 if( pVal )
348 pVal->PutDate( n );
350 else
352 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT );
354 break;
355 case SbxBYREF | SbxCHAR:
356 if( n > SbxMAXCHAR )
358 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXCHAR;
360 else if( n < SbxMINCHAR )
362 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINCHAR;
364 *p->pChar = static_cast<sal_Unicode>(n);
365 break;
366 case SbxBYREF | SbxBYTE:
367 if( n > SbxMAXBYTE )
369 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXBYTE;
371 else if( n < 0 )
373 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0;
375 *p->pByte = static_cast<sal_uInt8>(n);
376 break;
377 case SbxBYREF | SbxINTEGER:
378 case SbxBYREF | SbxBOOL:
379 if( n > SbxMAXINT )
381 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXINT;
383 else if( n < SbxMININT )
385 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMININT;
387 *p->pInteger = static_cast<sal_Int16>(n);
388 break;
389 case SbxBYREF | SbxERROR:
390 case SbxBYREF | SbxUSHORT:
391 if( n > SbxMAXUINT )
393 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXUINT;
395 else if( n < 0 )
397 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0;
399 *p->pUShort = static_cast<sal_uInt16>(n);
400 break;
401 case SbxBYREF | SbxLONG:
402 if( n > SbxMAXLNG )
404 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXLNG;
406 else if( n < SbxMINLNG )
408 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINLNG;
410 *p->pLong = static_cast<sal_Int32>(n);
411 break;
412 case SbxBYREF | SbxULONG:
413 if( n > SbxMAXULNG )
415 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXULNG;
417 else if( n < 0 )
419 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = 0;
421 *p->pULong = static_cast<sal_uInt32>(n);
422 break;
423 case SbxBYREF | SbxSINGLE:
424 if( n > SbxMAXSNG )
426 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXSNG;
428 else if( n < SbxMINSNG )
430 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINSNG;
432 *p->pSingle = static_cast<float>(n);
433 break;
434 case SbxBYREF | SbxSALINT64:
435 *p->pnInt64 = ImpDoubleToSalInt64( n );
436 break;
437 case SbxBYREF | SbxSALUINT64:
438 *p->puInt64 = ImpDoubleToSalUInt64( n );
439 break;
440 case SbxBYREF | SbxDATE:
441 case SbxBYREF | SbxDOUBLE:
442 *p->pDouble = n;
443 break;
444 case SbxBYREF | SbxCURRENCY:
445 if( n > SbxMAXCURR )
447 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMAXCURR;
449 else if( n < SbxMINCURR )
451 SbxBase::SetError( ERRCODE_BASIC_MATH_OVERFLOW ); n = SbxMINCURR;
453 *p->pnInt64 = ImpDoubleToCurrency( n );
454 break;
455 default:
456 SbxBase::SetError( ERRCODE_BASIC_CONVERSION );
457 break;
461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */