490 lines
18 KiB
C++
490 lines
18 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_connectivity.hxx"
|
|
#include <connectivity/dbconversion.hxx>
|
|
#include <connectivity/dbcharset.hxx>
|
|
#include <osl/diagnose.h>
|
|
#ifndef _INC_STDIO
|
|
#include <stdio.h>
|
|
#endif
|
|
#include <com/sun/star/sdbc/SQLException.hpp>
|
|
#include <com/sun/star/util/Date.hpp>
|
|
#include <com/sun/star/util/Time.hpp>
|
|
#include <com/sun/star/util/DateTime.hpp>
|
|
#include <rtl/ustrbuf.hxx>
|
|
|
|
#define MAX_DAYS 3636532
|
|
|
|
//.........................................................................
|
|
namespace dbtools
|
|
{
|
|
//.........................................................................
|
|
|
|
|
|
using namespace ::comphelper;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::util;
|
|
using namespace ::com::sun::star::sdb;
|
|
using namespace ::com::sun::star::sdbc;
|
|
using namespace ::com::sun::star::lang;
|
|
using namespace ::com::sun::star::beans;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
::com::sun::star::util::Date DBTypeConversion::getStandardDate()
|
|
{
|
|
static ::com::sun::star::util::Date STANDARD_DB_DATE(1,1,1900);
|
|
return STANDARD_DB_DATE;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
::rtl::OUString DBTypeConversion::toDateString(const Date& rDate)
|
|
{
|
|
sal_Char s[11];
|
|
snprintf(s,
|
|
sizeof(s),
|
|
"%04d-%02d-%02d",
|
|
(int)rDate.Year,
|
|
(int)rDate.Month,
|
|
(int)rDate.Day);
|
|
s[10] = 0;
|
|
return ::rtl::OUString::createFromAscii(s);
|
|
}
|
|
//------------------------------------------------------------------
|
|
::rtl::OUString DBTypeConversion::toTimeString(const Time& rTime)
|
|
{
|
|
sal_Char s[9];
|
|
snprintf(s,
|
|
sizeof(s),
|
|
"%02d:%02d:%02d",
|
|
(int)rTime.Hours,
|
|
(int)rTime.Minutes,
|
|
(int)rTime.Seconds);
|
|
s[8] = 0;
|
|
return ::rtl::OUString::createFromAscii(s);
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
::rtl::OUString DBTypeConversion::toDateTimeString(const DateTime& _rDateTime)
|
|
{
|
|
Date aDate(_rDateTime.Day,_rDateTime.Month,_rDateTime.Year);
|
|
::rtl::OUStringBuffer aTemp(toDateString(aDate));
|
|
aTemp.appendAscii(" ");
|
|
Time aTime(0,_rDateTime.Seconds,_rDateTime.Minutes,_rDateTime.Hours);
|
|
aTemp.append( toTimeString(aTime) );
|
|
aTemp.appendAscii(".");
|
|
aTemp.append( static_cast<sal_Int32>(_rDateTime.HundredthSeconds));
|
|
return aTemp.makeStringAndClear();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
Date DBTypeConversion::toDate(sal_Int32 _nVal)
|
|
{
|
|
Date aReturn;
|
|
aReturn.Day = (sal_uInt16)(_nVal % 100);
|
|
aReturn.Month = (sal_uInt16)((_nVal / 100) % 100);
|
|
aReturn.Year = (sal_uInt16)(_nVal / 10000);
|
|
return aReturn;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Time DBTypeConversion::toTime(sal_Int32 _nVal)
|
|
{
|
|
Time aReturn;
|
|
aReturn.Hours = (sal_uInt16)(((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 1000000);
|
|
aReturn.Minutes = (sal_uInt16)((((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 10000) % 100);
|
|
aReturn.Seconds = (sal_uInt16)((((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 100) % 100);
|
|
aReturn.HundredthSeconds = (sal_uInt16)(((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) % 100);
|
|
return aReturn;
|
|
}
|
|
|
|
const double fMilliSecondsPerDay = 86400000.0;
|
|
//------------------------------------------------------------------------------
|
|
sal_Int32 DBTypeConversion::toINT32(const Date& rVal)
|
|
{
|
|
return ((sal_Int32)(rVal.Day%100)) +
|
|
(((sal_Int32)(rVal.Month%100))*100) +
|
|
(((sal_Int32) rVal.Year%10000)*10000);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Int32 DBTypeConversion::toINT32(const Time& rVal)
|
|
{
|
|
// Zeit normalisieren
|
|
sal_Int32 nSeconds = rVal.Seconds + rVal.HundredthSeconds / 100;
|
|
sal_Int32 nHundredthSeconds = rVal.HundredthSeconds % 100;
|
|
sal_Int32 nMinutes = rVal.Minutes + nSeconds / 60;
|
|
nSeconds = nSeconds % 60;
|
|
sal_Int32 nHours = rVal.Hours + nMinutes / 60;
|
|
nMinutes = nMinutes % 60;
|
|
|
|
// Zeit zusammenbauen
|
|
return (sal_Int32)(nHundredthSeconds + (nSeconds*100) + (nMinutes*10000) + (nHours*1000000));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Int64 DBTypeConversion::toINT64(const DateTime& rVal)
|
|
{
|
|
// Zeit normalisieren
|
|
sal_Int32 nSeconds = rVal.Seconds + rVal.HundredthSeconds / 100;
|
|
sal_Int32 nHundredthSeconds = rVal.HundredthSeconds % 100;
|
|
sal_Int32 nMinutes = rVal.Minutes + nSeconds / 60;
|
|
nSeconds = nSeconds % 60;
|
|
sal_Int32 nHours = rVal.Hours + nMinutes / 60;
|
|
nMinutes = nMinutes % 60;
|
|
|
|
// Zeit zusammenbauen
|
|
sal_Int32 nTime = (sal_Int32)(nHundredthSeconds + (nSeconds*100) + (nMinutes*10000) + (nHours*1000000));
|
|
sal_Int32 nDate = ((sal_Int32)(rVal.Day%100)) + (((sal_Int32)(rVal.Month%100))*100) + (((sal_Int32) rVal.Year%10000)*10000);
|
|
sal_Int64 nRet;
|
|
|
|
nRet = (sal_Int64) nTime;
|
|
nRet <<= 32;
|
|
nRet += nDate;
|
|
|
|
return nRet;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
sal_Int32 DBTypeConversion::getMsFromTime(const Time& rVal)
|
|
{
|
|
sal_Int32 nHour = rVal.Hours;
|
|
sal_Int32 nMin = rVal.Minutes;
|
|
sal_Int32 nSec = rVal.Seconds;
|
|
sal_Int32 n100Sec = rVal.HundredthSeconds;
|
|
|
|
return ((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static sal_Int32 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30,
|
|
31, 31, 30, 31, 30, 31 };
|
|
|
|
//------------------------------------------------------------------------------
|
|
static sal_Bool implIsLeapYear(sal_Int32 _nYear)
|
|
{
|
|
return ( ( ((_nYear % 4) == 0)
|
|
&& ((_nYear % 100) != 0)
|
|
)
|
|
)
|
|
|| ((_nYear % 400) == 0)
|
|
;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static sal_Int32 implDaysInMonth(sal_Int32 _nMonth, sal_Int32 _nYear)
|
|
{
|
|
OSL_ENSURE(_nMonth > 0 && _nMonth < 13,"Month as invalid value!");
|
|
if (_nMonth != 2)
|
|
return aDaysInMonth[_nMonth-1];
|
|
else
|
|
{
|
|
if (implIsLeapYear(_nYear))
|
|
return aDaysInMonth[_nMonth-1] + 1;
|
|
else
|
|
return aDaysInMonth[_nMonth-1];
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static sal_Int32 implRelativeToAbsoluteNull(const Date& _rDate)
|
|
{
|
|
sal_Int32 nDays = 0;
|
|
|
|
// ripped this code from the implementation of tools::Date
|
|
sal_Int32 nNormalizedYear = _rDate.Year - 1;
|
|
nDays = nNormalizedYear * 365;
|
|
// leap years
|
|
nDays += (nNormalizedYear / 4) - (nNormalizedYear / 100) + (nNormalizedYear / 400);
|
|
|
|
for (sal_Int32 i = 1; i < _rDate.Month; ++i)
|
|
nDays += implDaysInMonth(i, _rDate.Year);
|
|
|
|
nDays += _rDate.Day;
|
|
return nDays;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
static void implBuildFromRelative( sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear)
|
|
{
|
|
sal_Int32 nTempDays;
|
|
sal_Int32 i = 0;
|
|
sal_Bool bCalc;
|
|
|
|
do
|
|
{
|
|
nTempDays = nDays;
|
|
rYear = (sal_uInt16)((nTempDays / 365) - i);
|
|
nTempDays -= (rYear-1) * 365;
|
|
nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400);
|
|
bCalc = sal_False;
|
|
if ( nTempDays < 1 )
|
|
{
|
|
i++;
|
|
bCalc = sal_True;
|
|
}
|
|
else
|
|
{
|
|
if ( nTempDays > 365 )
|
|
{
|
|
if ( (nTempDays != 366) || !implIsLeapYear( rYear ) )
|
|
{
|
|
i--;
|
|
bCalc = sal_True;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while ( bCalc );
|
|
|
|
rMonth = 1;
|
|
while ( nTempDays > implDaysInMonth( rMonth, rYear ) )
|
|
{
|
|
nTempDays -= implDaysInMonth( rMonth, rYear );
|
|
rMonth++;
|
|
}
|
|
rDay = (sal_uInt16)nTempDays;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
sal_Int32 DBTypeConversion::toDays(const Date& _rVal, const Date& _rNullDate)
|
|
{
|
|
return implRelativeToAbsoluteNull(_rVal) - implRelativeToAbsoluteNull(_rNullDate);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
double DBTypeConversion::toDouble(const Date& rVal, const Date& _rNullDate)
|
|
{
|
|
return (double)toDays(rVal, _rNullDate);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
double DBTypeConversion::toDouble(const Time& rVal)
|
|
{
|
|
return (double)getMsFromTime(rVal) / fMilliSecondsPerDay;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
double DBTypeConversion::toDouble(const DateTime& _rVal, const Date& _rNullDate)
|
|
{
|
|
sal_Int64 nTime = toDays(Date(_rVal.Day, _rVal.Month, _rVal.Year), _rNullDate);
|
|
Time aTimePart;
|
|
|
|
aTimePart.Hours = _rVal.Hours;
|
|
aTimePart.Minutes = _rVal.Minutes;
|
|
aTimePart.Seconds = _rVal.Seconds;
|
|
aTimePart.HundredthSeconds = _rVal.HundredthSeconds;
|
|
|
|
return ((double)nTime) + toDouble(aTimePart);
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
static void addDays(sal_Int32 nDays, Date& _rDate)
|
|
{
|
|
sal_Int32 nTempDays = implRelativeToAbsoluteNull( _rDate );
|
|
|
|
nTempDays += nDays;
|
|
if ( nTempDays > MAX_DAYS )
|
|
{
|
|
_rDate.Day = 31;
|
|
_rDate.Month = 12;
|
|
_rDate.Year = 9999;
|
|
}
|
|
else if ( nTempDays <= 0 )
|
|
{
|
|
_rDate.Day = 1;
|
|
_rDate.Month = 1;
|
|
_rDate.Year = 00;
|
|
}
|
|
else
|
|
implBuildFromRelative( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year );
|
|
}
|
|
// -----------------------------------------------------------------------
|
|
static void subDays( sal_Int32 nDays, Date& _rDate )
|
|
{
|
|
sal_Int32 nTempDays = implRelativeToAbsoluteNull( _rDate );
|
|
|
|
nTempDays -= nDays;
|
|
if ( nTempDays > MAX_DAYS )
|
|
{
|
|
_rDate.Day = 31;
|
|
_rDate.Month = 12;
|
|
_rDate.Year = 9999;
|
|
}
|
|
else if ( nTempDays <= 0 )
|
|
{
|
|
_rDate.Day = 1;
|
|
_rDate.Month = 1;
|
|
_rDate.Year = 00;
|
|
}
|
|
else
|
|
implBuildFromRelative( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year );
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
Date DBTypeConversion::toDate(double dVal, const Date& _rNullDate)
|
|
{
|
|
Date aRet = _rNullDate;
|
|
|
|
if (dVal >= 0)
|
|
addDays((sal_Int32)dVal,aRet);
|
|
else
|
|
subDays((sal_uInt32)(-dVal),aRet);
|
|
// x -= (sal_uInt32)(-nDays);
|
|
|
|
return aRet;
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
Time DBTypeConversion::toTime(double dVal)
|
|
{
|
|
sal_Int32 nDays = (sal_Int32)dVal;
|
|
sal_Int32 nMS = sal_Int32((dVal - (double)nDays) * fMilliSecondsPerDay + 0.5);
|
|
|
|
sal_Int16 nSign;
|
|
if ( nMS < 0 )
|
|
{
|
|
nMS *= -1;
|
|
nSign = -1;
|
|
}
|
|
else
|
|
nSign = 1;
|
|
|
|
Time xRet;
|
|
// Zeit normalisieren
|
|
// we have to sal_Int32 here because otherwise we get an overflow
|
|
sal_Int32 nHundredthSeconds = nMS/10;
|
|
sal_Int32 nSeconds = nHundredthSeconds / 100;
|
|
sal_Int32 nMinutes = nSeconds / 60;
|
|
|
|
xRet.HundredthSeconds = (sal_uInt16)(nHundredthSeconds % 100);
|
|
xRet.Seconds = (sal_uInt16)(nSeconds % 60);
|
|
xRet.Hours = (sal_uInt16)(nMinutes / 60);
|
|
xRet.Minutes = (sal_uInt16)(nMinutes % 60);
|
|
|
|
// Zeit zusammenbauen
|
|
sal_Int32 nTime = (sal_Int32)(xRet.HundredthSeconds + (xRet.Seconds*100) + (xRet.Minutes*10000) + (xRet.Hours*1000000)) * nSign;
|
|
|
|
if(nTime < 0)
|
|
{
|
|
xRet.HundredthSeconds = 99;
|
|
xRet.Minutes = 59;
|
|
xRet.Seconds = 59;
|
|
xRet.Hours = 23;
|
|
}
|
|
return xRet;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
DateTime DBTypeConversion::toDateTime(double dVal, const Date& _rNullDate)
|
|
{
|
|
Date aDate = toDate(dVal, _rNullDate);
|
|
Time aTime = toTime(dVal);
|
|
|
|
DateTime xRet;
|
|
|
|
xRet.Day = aDate.Day;
|
|
xRet.Month = aDate.Month;
|
|
xRet.Year = aDate.Year;
|
|
|
|
xRet.HundredthSeconds = aTime.HundredthSeconds;
|
|
xRet.Minutes = aTime.Minutes;
|
|
xRet.Seconds = aTime.Seconds;
|
|
xRet.Hours = aTime.Hours;
|
|
|
|
|
|
return xRet;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
Date DBTypeConversion::toDate(const ::rtl::OUString& _sSQLString)
|
|
{
|
|
// get the token out of a string
|
|
static sal_Unicode sDateSep = '-';
|
|
|
|
sal_Int32 nIndex = 0;
|
|
sal_uInt16 nYear = 0,
|
|
nMonth = 0,
|
|
nDay = 0;
|
|
nYear = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32();
|
|
if(nIndex != -1)
|
|
{
|
|
nMonth = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32();
|
|
if(nIndex != -1)
|
|
nDay = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32();
|
|
}
|
|
|
|
return Date(nDay,nMonth,nYear);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
DateTime DBTypeConversion::toDateTime(const ::rtl::OUString& _sSQLString)
|
|
{
|
|
//@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Timestamp.html#valueOf(java.lang.String)
|
|
//@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Date.html#valueOf(java.lang.String)
|
|
//@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Time.html#valueOf(java.lang.String)
|
|
|
|
// the date part
|
|
Date aDate = toDate(_sSQLString);
|
|
Time aTime;
|
|
sal_Int32 nSeparation = _sSQLString.indexOf( ' ' );
|
|
if ( -1 != nSeparation )
|
|
aTime = toTime( _sSQLString.copy( nSeparation ) );
|
|
|
|
return DateTime(aTime.HundredthSeconds,aTime.Seconds,aTime.Minutes,aTime.Hours,aDate.Day,aDate.Month,aDate.Year);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Time DBTypeConversion::toTime(const ::rtl::OUString& _sSQLString)
|
|
{
|
|
static sal_Unicode sTimeSep = ':';
|
|
|
|
sal_Int32 nIndex = 0;
|
|
sal_uInt16 nHour = 0,
|
|
nMinute = 0,
|
|
nSecond = 0,
|
|
nHundredthSeconds = 0;
|
|
nHour = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32();
|
|
if(nIndex != -1)
|
|
{
|
|
nMinute = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32();
|
|
if(nIndex != -1)
|
|
{
|
|
nSecond = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32();
|
|
nIndex = 0;
|
|
::rtl::OUString sNano(_sSQLString.getToken(1,'.',nIndex));
|
|
if ( sNano.getLength() )
|
|
{
|
|
// our time struct only supports hundredth seconds
|
|
sNano = sNano.copy(0,::std::min<sal_Int32>(sNano.getLength(),2));
|
|
const static ::rtl::OUString s_Zeros(RTL_CONSTASCII_USTRINGPARAM("00"));
|
|
sNano += s_Zeros.copy(0,s_Zeros.getLength() - sNano.getLength());
|
|
nHundredthSeconds = static_cast<sal_uInt16>(sNano.toInt32());
|
|
}
|
|
}
|
|
}
|
|
return Time(nHundredthSeconds,nSecond,nMinute,nHour);
|
|
}
|
|
|
|
//.........................................................................
|
|
} // namespace dbtools
|
|
//.........................................................................
|
|
|
|
|