update dev300-m58
[ooovba.git] / connectivity / source / commontools / dbconversion.cxx
blobd2682adf7b6c9afeb3ad16b364c3b2485d3b6341
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dbconversion.cxx,v $
10 * $Revision: 1.29 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include <connectivity/dbconversion.hxx>
34 #include <connectivity/dbcharset.hxx>
35 #include <osl/diagnose.h>
36 #ifndef _INC_STDIO
37 #include <stdio.h>
38 #endif
39 #include <com/sun/star/sdbc/SQLException.hpp>
40 #include <com/sun/star/util/Date.hpp>
41 #include <com/sun/star/util/Time.hpp>
42 #include <com/sun/star/util/DateTime.hpp>
43 #include <rtl/ustrbuf.hxx>
45 #define MAX_DAYS 3636532
47 //.........................................................................
48 namespace dbtools
50 //.........................................................................
53 using namespace ::comphelper;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::util;
56 using namespace ::com::sun::star::sdb;
57 using namespace ::com::sun::star::sdbc;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::beans;
62 //------------------------------------------------------------------------------
63 ::com::sun::star::util::Date DBTypeConversion::getStandardDate()
65 static ::com::sun::star::util::Date STANDARD_DB_DATE(1,1,1900);
66 return STANDARD_DB_DATE;
68 //------------------------------------------------------------------------------
69 ::rtl::OUString DBTypeConversion::toDateString(const Date& rDate)
71 sal_Char s[11];
72 snprintf(s,
73 sizeof(s),
74 "%04d-%02d-%02d",
75 (int)rDate.Year,
76 (int)rDate.Month,
77 (int)rDate.Day);
78 s[10] = 0;
79 return ::rtl::OUString::createFromAscii(s);
81 //------------------------------------------------------------------
82 ::rtl::OUString DBTypeConversion::toTimeString(const Time& rTime)
84 sal_Char s[9];
85 snprintf(s,
86 sizeof(s),
87 "%02d:%02d:%02d",
88 (int)rTime.Hours,
89 (int)rTime.Minutes,
90 (int)rTime.Seconds);
91 s[8] = 0;
92 return ::rtl::OUString::createFromAscii(s);
95 //------------------------------------------------------------------
96 ::rtl::OUString DBTypeConversion::toDateTimeString(const DateTime& _rDateTime)
98 Date aDate(_rDateTime.Day,_rDateTime.Month,_rDateTime.Year);
99 ::rtl::OUStringBuffer aTemp(toDateString(aDate));
100 aTemp.appendAscii(" ");
101 Time aTime(0,_rDateTime.Seconds,_rDateTime.Minutes,_rDateTime.Hours);
102 aTemp.append( toTimeString(aTime) );
103 aTemp.appendAscii(".");
104 aTemp.append( static_cast<sal_Int32>(_rDateTime.HundredthSeconds));
105 return aTemp.makeStringAndClear();
107 //------------------------------------------------------------------------------
108 Date DBTypeConversion::toDate(sal_Int32 _nVal)
110 Date aReturn;
111 aReturn.Day = (sal_uInt16)(_nVal % 100);
112 aReturn.Month = (sal_uInt16)((_nVal / 100) % 100);
113 aReturn.Year = (sal_uInt16)(_nVal / 10000);
114 return aReturn;
117 //------------------------------------------------------------------------------
118 Time DBTypeConversion::toTime(sal_Int32 _nVal)
120 Time aReturn;
121 aReturn.Hours = (sal_uInt16)(((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 1000000);
122 aReturn.Minutes = (sal_uInt16)((((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 10000) % 100);
123 aReturn.Seconds = (sal_uInt16)((((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 100) % 100);
124 aReturn.HundredthSeconds = (sal_uInt16)(((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) % 100);
125 return aReturn;
128 const double fMilliSecondsPerDay = 86400000.0;
129 //------------------------------------------------------------------------------
130 sal_Int32 DBTypeConversion::toINT32(const Date& rVal)
132 return ((sal_Int32)(rVal.Day%100)) +
133 (((sal_Int32)(rVal.Month%100))*100) +
134 (((sal_Int32) rVal.Year%10000)*10000);
137 //------------------------------------------------------------------------------
138 sal_Int32 DBTypeConversion::toINT32(const Time& rVal)
140 // Zeit normalisieren
141 sal_Int32 nSeconds = rVal.Seconds + rVal.HundredthSeconds / 100;
142 sal_Int32 nHundredthSeconds = rVal.HundredthSeconds % 100;
143 sal_Int32 nMinutes = rVal.Minutes + nSeconds / 60;
144 nSeconds = nSeconds % 60;
145 sal_Int32 nHours = rVal.Hours + nMinutes / 60;
146 nMinutes = nMinutes % 60;
148 // Zeit zusammenbauen
149 return (sal_Int32)(nHundredthSeconds + (nSeconds*100) + (nMinutes*10000) + (nHours*1000000));
152 //------------------------------------------------------------------------------
153 sal_Int64 DBTypeConversion::toINT64(const DateTime& rVal)
155 // Zeit normalisieren
156 sal_Int32 nSeconds = rVal.Seconds + rVal.HundredthSeconds / 100;
157 sal_Int32 nHundredthSeconds = rVal.HundredthSeconds % 100;
158 sal_Int32 nMinutes = rVal.Minutes + nSeconds / 60;
159 nSeconds = nSeconds % 60;
160 sal_Int32 nHours = rVal.Hours + nMinutes / 60;
161 nMinutes = nMinutes % 60;
163 // Zeit zusammenbauen
164 sal_Int32 nTime = (sal_Int32)(nHundredthSeconds + (nSeconds*100) + (nMinutes*10000) + (nHours*1000000));
165 sal_Int32 nDate = ((sal_Int32)(rVal.Day%100)) + (((sal_Int32)(rVal.Month%100))*100) + (((sal_Int32) rVal.Year%10000)*10000);
166 sal_Int64 nRet;
168 nRet = (sal_Int64) nTime;
169 nRet <<= 32;
170 nRet += nDate;
172 return nRet;
175 //------------------------------------------------------------------------------
176 sal_Int32 DBTypeConversion::getMsFromTime(const Time& rVal)
178 sal_Int32 nHour = rVal.Hours;
179 sal_Int32 nMin = rVal.Minutes;
180 sal_Int32 nSec = rVal.Seconds;
181 sal_Int32 n100Sec = rVal.HundredthSeconds;
183 return ((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10));
186 //------------------------------------------------------------------------------
187 static sal_Int32 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30,
188 31, 31, 30, 31, 30, 31 };
190 //------------------------------------------------------------------------------
191 static sal_Bool implIsLeapYear(sal_Int32 _nYear)
193 return ( ( ((_nYear % 4) == 0)
194 && ((_nYear % 100) != 0)
197 || ((_nYear % 400) == 0)
201 //------------------------------------------------------------------------------
202 static sal_Int32 implDaysInMonth(sal_Int32 _nMonth, sal_Int32 _nYear)
204 OSL_ENSURE(_nMonth > 0 && _nMonth < 13,"Month as invalid value!");
205 if (_nMonth != 2)
206 return aDaysInMonth[_nMonth-1];
207 else
209 if (implIsLeapYear(_nYear))
210 return aDaysInMonth[_nMonth-1] + 1;
211 else
212 return aDaysInMonth[_nMonth-1];
216 //------------------------------------------------------------------------------
217 static sal_Int32 implRelativeToAbsoluteNull(const Date& _rDate)
219 sal_Int32 nDays = 0;
221 // ripped this code from the implementation of tools::Date
222 sal_Int32 nNormalizedYear = _rDate.Year - 1;
223 nDays = nNormalizedYear * 365;
224 // leap years
225 nDays += (nNormalizedYear / 4) - (nNormalizedYear / 100) + (nNormalizedYear / 400);
227 for (sal_Int32 i = 1; i < _rDate.Month; ++i)
228 nDays += implDaysInMonth(i, _rDate.Year);
230 nDays += _rDate.Day;
231 return nDays;
233 //------------------------------------------------------------------------------
234 static void implBuildFromRelative( sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear)
236 sal_Int32 nTempDays;
237 sal_Int32 i = 0;
238 sal_Bool bCalc;
242 nTempDays = nDays;
243 rYear = (sal_uInt16)((nTempDays / 365) - i);
244 nTempDays -= (rYear-1) * 365;
245 nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400);
246 bCalc = sal_False;
247 if ( nTempDays < 1 )
249 i++;
250 bCalc = sal_True;
252 else
254 if ( nTempDays > 365 )
256 if ( (nTempDays != 366) || !implIsLeapYear( rYear ) )
258 i--;
259 bCalc = sal_True;
264 while ( bCalc );
266 rMonth = 1;
267 while ( nTempDays > implDaysInMonth( rMonth, rYear ) )
269 nTempDays -= implDaysInMonth( rMonth, rYear );
270 rMonth++;
272 rDay = (sal_uInt16)nTempDays;
274 //------------------------------------------------------------------------------
275 sal_Int32 DBTypeConversion::toDays(const Date& _rVal, const Date& _rNullDate)
277 return implRelativeToAbsoluteNull(_rVal) - implRelativeToAbsoluteNull(_rNullDate);
280 //------------------------------------------------------------------------------
281 double DBTypeConversion::toDouble(const Date& rVal, const Date& _rNullDate)
283 return (double)toDays(rVal, _rNullDate);
286 //------------------------------------------------------------------------------
287 double DBTypeConversion::toDouble(const Time& rVal)
289 return (double)getMsFromTime(rVal) / fMilliSecondsPerDay;
292 //------------------------------------------------------------------------------
293 double DBTypeConversion::toDouble(const DateTime& _rVal, const Date& _rNullDate)
295 sal_Int64 nTime = toDays(Date(_rVal.Day, _rVal.Month, _rVal.Year), _rNullDate);
296 Time aTimePart;
298 aTimePart.Hours = _rVal.Hours;
299 aTimePart.Minutes = _rVal.Minutes;
300 aTimePart.Seconds = _rVal.Seconds;
301 aTimePart.HundredthSeconds = _rVal.HundredthSeconds;
303 return ((double)nTime) + toDouble(aTimePart);
305 // -------------------------------------------------------------------------
306 static void addDays(sal_Int32 nDays, Date& _rDate)
308 sal_Int32 nTempDays = implRelativeToAbsoluteNull( _rDate );
310 nTempDays += nDays;
311 if ( nTempDays > MAX_DAYS )
313 _rDate.Day = 31;
314 _rDate.Month = 12;
315 _rDate.Year = 9999;
317 else if ( nTempDays <= 0 )
319 _rDate.Day = 1;
320 _rDate.Month = 1;
321 _rDate.Year = 00;
323 else
324 implBuildFromRelative( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year );
326 // -----------------------------------------------------------------------
327 static void subDays( sal_Int32 nDays, Date& _rDate )
329 sal_Int32 nTempDays = implRelativeToAbsoluteNull( _rDate );
331 nTempDays -= nDays;
332 if ( nTempDays > MAX_DAYS )
334 _rDate.Day = 31;
335 _rDate.Month = 12;
336 _rDate.Year = 9999;
338 else if ( nTempDays <= 0 )
340 _rDate.Day = 1;
341 _rDate.Month = 1;
342 _rDate.Year = 00;
344 else
345 implBuildFromRelative( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year );
347 // -------------------------------------------------------------------------
348 Date DBTypeConversion::toDate(double dVal, const Date& _rNullDate)
350 Date aRet = _rNullDate;
352 if (dVal >= 0)
353 addDays((sal_Int32)dVal,aRet);
354 else
355 subDays((sal_uInt32)(-dVal),aRet);
356 // x -= (sal_uInt32)(-nDays);
358 return aRet;
360 // -------------------------------------------------------------------------
361 Time DBTypeConversion::toTime(double dVal)
363 sal_Int32 nDays = (sal_Int32)dVal;
364 sal_Int32 nMS = sal_Int32((dVal - (double)nDays) * fMilliSecondsPerDay + 0.5);
366 sal_Int16 nSign;
367 if ( nMS < 0 )
369 nMS *= -1;
370 nSign = -1;
372 else
373 nSign = 1;
375 Time xRet;
376 // Zeit normalisieren
377 // we have to sal_Int32 here because otherwise we get an overflow
378 sal_Int32 nHundredthSeconds = nMS/10;
379 sal_Int32 nSeconds = nHundredthSeconds / 100;
380 sal_Int32 nMinutes = nSeconds / 60;
382 xRet.HundredthSeconds = (sal_uInt16)(nHundredthSeconds % 100);
383 xRet.Seconds = (sal_uInt16)(nSeconds % 60);
384 xRet.Hours = (sal_uInt16)(nMinutes / 60);
385 xRet.Minutes = (sal_uInt16)(nMinutes % 60);
387 // Zeit zusammenbauen
388 sal_Int32 nTime = (sal_Int32)(xRet.HundredthSeconds + (xRet.Seconds*100) + (xRet.Minutes*10000) + (xRet.Hours*1000000)) * nSign;
390 if(nTime < 0)
392 xRet.HundredthSeconds = 99;
393 xRet.Minutes = 59;
394 xRet.Seconds = 59;
395 xRet.Hours = 23;
397 return xRet;
399 //------------------------------------------------------------------------------
400 DateTime DBTypeConversion::toDateTime(double dVal, const Date& _rNullDate)
402 Date aDate = toDate(dVal, _rNullDate);
403 Time aTime = toTime(dVal);
405 DateTime xRet;
407 xRet.Day = aDate.Day;
408 xRet.Month = aDate.Month;
409 xRet.Year = aDate.Year;
411 xRet.HundredthSeconds = aTime.HundredthSeconds;
412 xRet.Minutes = aTime.Minutes;
413 xRet.Seconds = aTime.Seconds;
414 xRet.Hours = aTime.Hours;
417 return xRet;
419 //------------------------------------------------------------------------------
420 Date DBTypeConversion::toDate(const ::rtl::OUString& _sSQLString)
422 // get the token out of a string
423 static sal_Unicode sDateSep = '-';
425 sal_Int32 nIndex = 0;
426 sal_uInt16 nYear = 0,
427 nMonth = 0,
428 nDay = 0;
429 nYear = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32();
430 if(nIndex != -1)
432 nMonth = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32();
433 if(nIndex != -1)
434 nDay = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32();
437 return Date(nDay,nMonth,nYear);
440 //-----------------------------------------------------------------------------
441 DateTime DBTypeConversion::toDateTime(const ::rtl::OUString& _sSQLString)
443 //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Timestamp.html#valueOf(java.lang.String)
444 //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Date.html#valueOf(java.lang.String)
445 //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Time.html#valueOf(java.lang.String)
447 // the date part
448 Date aDate = toDate(_sSQLString);
449 Time aTime;
450 sal_Int32 nSeparation = _sSQLString.indexOf( ' ' );
451 if ( -1 != nSeparation )
452 aTime = toTime( _sSQLString.copy( nSeparation ) );
454 return DateTime(aTime.HundredthSeconds,aTime.Seconds,aTime.Minutes,aTime.Hours,aDate.Day,aDate.Month,aDate.Year);
457 //-----------------------------------------------------------------------------
458 Time DBTypeConversion::toTime(const ::rtl::OUString& _sSQLString)
460 static sal_Unicode sTimeSep = ':';
462 sal_Int32 nIndex = 0;
463 sal_uInt16 nHour = 0,
464 nMinute = 0,
465 nSecond = 0,
466 nHundredthSeconds = 0;
467 nHour = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32();
468 if(nIndex != -1)
470 nMinute = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32();
471 if(nIndex != -1)
473 nSecond = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32();
474 nIndex = 0;
475 ::rtl::OUString sNano(_sSQLString.getToken(1,'.',nIndex));
476 if ( sNano.getLength() )
478 // our time struct only supports hundredth seconds
479 sNano = sNano.copy(0,::std::min<sal_Int32>(sNano.getLength(),2));
480 const static ::rtl::OUString s_Zeros(RTL_CONSTASCII_USTRINGPARAM("00"));
481 sNano += s_Zeros.copy(0,s_Zeros.getLength() - sNano.getLength());
482 nHundredthSeconds = static_cast<sal_uInt16>(sNano.toInt32());
486 return Time(nHundredthSeconds,nSecond,nMinute,nHour);
489 //.........................................................................
490 } // namespace dbtools
491 //.........................................................................