1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dbconversion.cxx,v $
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>
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 //.........................................................................
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
)
79 return ::rtl::OUString::createFromAscii(s
);
81 //------------------------------------------------------------------
82 ::rtl::OUString
DBTypeConversion::toTimeString(const Time
& rTime
)
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
)
111 aReturn
.Day
= (sal_uInt16
)(_nVal
% 100);
112 aReturn
.Month
= (sal_uInt16
)((_nVal
/ 100) % 100);
113 aReturn
.Year
= (sal_uInt16
)(_nVal
/ 10000);
117 //------------------------------------------------------------------------------
118 Time
DBTypeConversion::toTime(sal_Int32 _nVal
)
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);
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);
168 nRet
= (sal_Int64
) nTime
;
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!");
206 return aDaysInMonth
[_nMonth
-1];
209 if (implIsLeapYear(_nYear
))
210 return aDaysInMonth
[_nMonth
-1] + 1;
212 return aDaysInMonth
[_nMonth
-1];
216 //------------------------------------------------------------------------------
217 static sal_Int32
implRelativeToAbsoluteNull(const Date
& _rDate
)
221 // ripped this code from the implementation of tools::Date
222 sal_Int32 nNormalizedYear
= _rDate
.Year
- 1;
223 nDays
= nNormalizedYear
* 365;
225 nDays
+= (nNormalizedYear
/ 4) - (nNormalizedYear
/ 100) + (nNormalizedYear
/ 400);
227 for (sal_Int32 i
= 1; i
< _rDate
.Month
; ++i
)
228 nDays
+= implDaysInMonth(i
, _rDate
.Year
);
233 //------------------------------------------------------------------------------
234 static void implBuildFromRelative( sal_Int32 nDays
, sal_uInt16
& rDay
, sal_uInt16
& rMonth
, sal_uInt16
& rYear
)
243 rYear
= (sal_uInt16
)((nTempDays
/ 365) - i
);
244 nTempDays
-= (rYear
-1) * 365;
245 nTempDays
-= ((rYear
-1) / 4) - ((rYear
-1) / 100) + ((rYear
-1) / 400);
254 if ( nTempDays
> 365 )
256 if ( (nTempDays
!= 366) || !implIsLeapYear( rYear
) )
267 while ( nTempDays
> implDaysInMonth( rMonth
, rYear
) )
269 nTempDays
-= implDaysInMonth( rMonth
, rYear
);
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
);
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
);
311 if ( nTempDays
> MAX_DAYS
)
317 else if ( nTempDays
<= 0 )
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
);
332 if ( nTempDays
> MAX_DAYS
)
338 else if ( nTempDays
<= 0 )
345 implBuildFromRelative( nTempDays
, _rDate
.Day
, _rDate
.Month
, _rDate
.Year
);
347 // -------------------------------------------------------------------------
348 Date
DBTypeConversion::toDate(double dVal
, const Date
& _rNullDate
)
350 Date aRet
= _rNullDate
;
353 addDays((sal_Int32
)dVal
,aRet
);
355 subDays((sal_uInt32
)(-dVal
),aRet
);
356 // x -= (sal_uInt32)(-nDays);
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);
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
;
392 xRet
.HundredthSeconds
= 99;
399 //------------------------------------------------------------------------------
400 DateTime
DBTypeConversion::toDateTime(double dVal
, const Date
& _rNullDate
)
402 Date aDate
= toDate(dVal
, _rNullDate
);
403 Time aTime
= toTime(dVal
);
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
;
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,
429 nYear
= (sal_uInt16
)_sSQLString
.getToken(0,sDateSep
,nIndex
).toInt32();
432 nMonth
= (sal_uInt16
)_sSQLString
.getToken(0,sDateSep
,nIndex
).toInt32();
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)
448 Date aDate
= toDate(_sSQLString
);
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,
466 nHundredthSeconds
= 0;
467 nHour
= (sal_uInt16
)_sSQLString
.getToken(0,sTimeSep
,nIndex
).toInt32();
470 nMinute
= (sal_uInt16
)_sSQLString
.getToken(0,sTimeSep
,nIndex
).toInt32();
473 nSecond
= (sal_uInt16
)_sSQLString
.getToken(0,sTimeSep
,nIndex
).toInt32();
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 //.........................................................................