1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_connectivity.hxx" 26 #include <connectivity/dbconversion.hxx> 27 #include <connectivity/dbcharset.hxx> 28 #include <osl/diagnose.h> 29 #ifndef _INC_STDIO 30 #include <stdio.h> 31 #endif 32 #include <com/sun/star/sdbc/SQLException.hpp> 33 #include <com/sun/star/util/Date.hpp> 34 #include <com/sun/star/util/Time.hpp> 35 #include <com/sun/star/util/DateTime.hpp> 36 #include <rtl/ustrbuf.hxx> 37 38 #define MAX_DAYS 3636532 39 40 //......................................................................... 41 namespace dbtools 42 { 43 //......................................................................... 44 45 46 using namespace ::comphelper; 47 using namespace ::com::sun::star::uno; 48 using namespace ::com::sun::star::util; 49 using namespace ::com::sun::star::sdb; 50 using namespace ::com::sun::star::sdbc; 51 using namespace ::com::sun::star::lang; 52 using namespace ::com::sun::star::beans; 53 54 55 //------------------------------------------------------------------------------ getStandardDate()56 ::com::sun::star::util::Date DBTypeConversion::getStandardDate() 57 { 58 static ::com::sun::star::util::Date STANDARD_DB_DATE(1,1,1900); 59 return STANDARD_DB_DATE; 60 } 61 //------------------------------------------------------------------------------ toDateString(const Date & rDate)62 ::rtl::OUString DBTypeConversion::toDateString(const Date& rDate) 63 { 64 sal_Char s[11]; 65 snprintf(s, 66 sizeof(s), 67 "%04d-%02d-%02d", 68 (int)rDate.Year, 69 (int)rDate.Month, 70 (int)rDate.Day); 71 s[10] = 0; 72 return ::rtl::OUString::createFromAscii(s); 73 } 74 //------------------------------------------------------------------ toTimeString(const Time & rTime)75 ::rtl::OUString DBTypeConversion::toTimeString(const Time& rTime) 76 { 77 sal_Char s[9]; 78 snprintf(s, 79 sizeof(s), 80 "%02d:%02d:%02d", 81 (int)rTime.Hours, 82 (int)rTime.Minutes, 83 (int)rTime.Seconds); 84 s[8] = 0; 85 return ::rtl::OUString::createFromAscii(s); 86 } 87 88 //------------------------------------------------------------------ toDateTimeString(const DateTime & _rDateTime)89 ::rtl::OUString DBTypeConversion::toDateTimeString(const DateTime& _rDateTime) 90 { 91 Date aDate(_rDateTime.Day,_rDateTime.Month,_rDateTime.Year); 92 ::rtl::OUStringBuffer aTemp(toDateString(aDate)); 93 aTemp.appendAscii(" "); 94 Time aTime(0,_rDateTime.Seconds,_rDateTime.Minutes,_rDateTime.Hours); 95 aTemp.append( toTimeString(aTime) ); 96 aTemp.appendAscii("."); 97 aTemp.append( static_cast<sal_Int32>(_rDateTime.HundredthSeconds)); 98 return aTemp.makeStringAndClear(); 99 } 100 //------------------------------------------------------------------------------ toDate(sal_Int32 _nVal)101 Date DBTypeConversion::toDate(sal_Int32 _nVal) 102 { 103 Date aReturn; 104 aReturn.Day = (sal_uInt16)(_nVal % 100); 105 aReturn.Month = (sal_uInt16)((_nVal / 100) % 100); 106 aReturn.Year = (sal_uInt16)(_nVal / 10000); 107 return aReturn; 108 } 109 110 //------------------------------------------------------------------------------ toTime(sal_Int32 _nVal)111 Time DBTypeConversion::toTime(sal_Int32 _nVal) 112 { 113 Time aReturn; 114 aReturn.Hours = (sal_uInt16)(((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 1000000); 115 aReturn.Minutes = (sal_uInt16)((((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 10000) % 100); 116 aReturn.Seconds = (sal_uInt16)((((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 100) % 100); 117 aReturn.HundredthSeconds = (sal_uInt16)(((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) % 100); 118 return aReturn; 119 } 120 121 const double fMilliSecondsPerDay = 86400000.0; 122 //------------------------------------------------------------------------------ toINT32(const Date & rVal)123 sal_Int32 DBTypeConversion::toINT32(const Date& rVal) 124 { 125 return ((sal_Int32)(rVal.Day%100)) + 126 (((sal_Int32)(rVal.Month%100))*100) + 127 (((sal_Int32) rVal.Year%10000)*10000); 128 } 129 130 //------------------------------------------------------------------------------ toINT32(const Time & rVal)131 sal_Int32 DBTypeConversion::toINT32(const Time& rVal) 132 { 133 // Zeit normalisieren 134 sal_Int32 nSeconds = rVal.Seconds + rVal.HundredthSeconds / 100; 135 sal_Int32 nHundredthSeconds = rVal.HundredthSeconds % 100; 136 sal_Int32 nMinutes = rVal.Minutes + nSeconds / 60; 137 nSeconds = nSeconds % 60; 138 sal_Int32 nHours = rVal.Hours + nMinutes / 60; 139 nMinutes = nMinutes % 60; 140 141 // Zeit zusammenbauen 142 return (sal_Int32)(nHundredthSeconds + (nSeconds*100) + (nMinutes*10000) + (nHours*1000000)); 143 } 144 145 //------------------------------------------------------------------------------ toINT64(const DateTime & rVal)146 sal_Int64 DBTypeConversion::toINT64(const DateTime& rVal) 147 { 148 // Zeit normalisieren 149 sal_Int32 nSeconds = rVal.Seconds + rVal.HundredthSeconds / 100; 150 sal_Int32 nHundredthSeconds = rVal.HundredthSeconds % 100; 151 sal_Int32 nMinutes = rVal.Minutes + nSeconds / 60; 152 nSeconds = nSeconds % 60; 153 sal_Int32 nHours = rVal.Hours + nMinutes / 60; 154 nMinutes = nMinutes % 60; 155 156 // Zeit zusammenbauen 157 sal_Int32 nTime = (sal_Int32)(nHundredthSeconds + (nSeconds*100) + (nMinutes*10000) + (nHours*1000000)); 158 sal_Int32 nDate = ((sal_Int32)(rVal.Day%100)) + (((sal_Int32)(rVal.Month%100))*100) + (((sal_Int32) rVal.Year%10000)*10000); 159 sal_Int64 nRet; 160 161 nRet = (sal_Int64) nTime; 162 nRet <<= 32; 163 nRet += nDate; 164 165 return nRet; 166 } 167 168 //------------------------------------------------------------------------------ getMsFromTime(const Time & rVal)169 sal_Int32 DBTypeConversion::getMsFromTime(const Time& rVal) 170 { 171 sal_Int32 nHour = rVal.Hours; 172 sal_Int32 nMin = rVal.Minutes; 173 sal_Int32 nSec = rVal.Seconds; 174 sal_Int32 n100Sec = rVal.HundredthSeconds; 175 176 return ((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10)); 177 } 178 179 //------------------------------------------------------------------------------ 180 static sal_Int32 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 181 31, 31, 30, 31, 30, 31 }; 182 183 //------------------------------------------------------------------------------ implIsLeapYear(sal_Int32 _nYear)184 static sal_Bool implIsLeapYear(sal_Int32 _nYear) 185 { 186 return ( ( ((_nYear % 4) == 0) 187 && ((_nYear % 100) != 0) 188 ) 189 ) 190 || ((_nYear % 400) == 0) 191 ; 192 } 193 194 //------------------------------------------------------------------------------ implDaysInMonth(sal_Int32 _nMonth,sal_Int32 _nYear)195 static sal_Int32 implDaysInMonth(sal_Int32 _nMonth, sal_Int32 _nYear) 196 { 197 OSL_ENSURE(_nMonth > 0 && _nMonth < 13,"Month as invalid value!"); 198 if (_nMonth != 2) 199 return aDaysInMonth[_nMonth-1]; 200 else 201 { 202 if (implIsLeapYear(_nYear)) 203 return aDaysInMonth[_nMonth-1] + 1; 204 else 205 return aDaysInMonth[_nMonth-1]; 206 } 207 } 208 209 //------------------------------------------------------------------------------ implRelativeToAbsoluteNull(const Date & _rDate)210 static sal_Int32 implRelativeToAbsoluteNull(const Date& _rDate) 211 { 212 sal_Int32 nDays = 0; 213 214 // ripped this code from the implementation of tools::Date 215 sal_Int32 nNormalizedYear = _rDate.Year - 1; 216 nDays = nNormalizedYear * 365; 217 // leap years 218 nDays += (nNormalizedYear / 4) - (nNormalizedYear / 100) + (nNormalizedYear / 400); 219 220 for (sal_Int32 i = 1; i < _rDate.Month; ++i) 221 nDays += implDaysInMonth(i, _rDate.Year); 222 223 nDays += _rDate.Day; 224 return nDays; 225 } 226 //------------------------------------------------------------------------------ implBuildFromRelative(sal_Int32 nDays,sal_uInt16 & rDay,sal_uInt16 & rMonth,sal_uInt16 & rYear)227 static void implBuildFromRelative( sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear) 228 { 229 sal_Int32 nTempDays; 230 sal_Int32 i = 0; 231 sal_Bool bCalc; 232 233 do 234 { 235 nTempDays = nDays; 236 rYear = (sal_uInt16)((nTempDays / 365) - i); 237 nTempDays -= (rYear-1) * 365; 238 nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400); 239 bCalc = sal_False; 240 if ( nTempDays < 1 ) 241 { 242 i++; 243 bCalc = sal_True; 244 } 245 else 246 { 247 if ( nTempDays > 365 ) 248 { 249 if ( (nTempDays != 366) || !implIsLeapYear( rYear ) ) 250 { 251 i--; 252 bCalc = sal_True; 253 } 254 } 255 } 256 } 257 while ( bCalc ); 258 259 rMonth = 1; 260 while ( nTempDays > implDaysInMonth( rMonth, rYear ) ) 261 { 262 nTempDays -= implDaysInMonth( rMonth, rYear ); 263 rMonth++; 264 } 265 rDay = (sal_uInt16)nTempDays; 266 } 267 //------------------------------------------------------------------------------ toDays(const Date & _rVal,const Date & _rNullDate)268 sal_Int32 DBTypeConversion::toDays(const Date& _rVal, const Date& _rNullDate) 269 { 270 return implRelativeToAbsoluteNull(_rVal) - implRelativeToAbsoluteNull(_rNullDate); 271 } 272 273 //------------------------------------------------------------------------------ toDouble(const Date & rVal,const Date & _rNullDate)274 double DBTypeConversion::toDouble(const Date& rVal, const Date& _rNullDate) 275 { 276 return (double)toDays(rVal, _rNullDate); 277 } 278 279 //------------------------------------------------------------------------------ toDouble(const Time & rVal)280 double DBTypeConversion::toDouble(const Time& rVal) 281 { 282 return (double)getMsFromTime(rVal) / fMilliSecondsPerDay; 283 } 284 285 //------------------------------------------------------------------------------ toDouble(const DateTime & _rVal,const Date & _rNullDate)286 double DBTypeConversion::toDouble(const DateTime& _rVal, const Date& _rNullDate) 287 { 288 sal_Int64 nTime = toDays(Date(_rVal.Day, _rVal.Month, _rVal.Year), _rNullDate); 289 Time aTimePart; 290 291 aTimePart.Hours = _rVal.Hours; 292 aTimePart.Minutes = _rVal.Minutes; 293 aTimePart.Seconds = _rVal.Seconds; 294 aTimePart.HundredthSeconds = _rVal.HundredthSeconds; 295 296 return ((double)nTime) + toDouble(aTimePart); 297 } 298 // ------------------------------------------------------------------------- addDays(sal_Int32 nDays,Date & _rDate)299 static void addDays(sal_Int32 nDays, Date& _rDate) 300 { 301 sal_Int32 nTempDays = implRelativeToAbsoluteNull( _rDate ); 302 303 nTempDays += nDays; 304 if ( nTempDays > MAX_DAYS ) 305 { 306 _rDate.Day = 31; 307 _rDate.Month = 12; 308 _rDate.Year = 9999; 309 } 310 else if ( nTempDays <= 0 ) 311 { 312 _rDate.Day = 1; 313 _rDate.Month = 1; 314 _rDate.Year = 00; 315 } 316 else 317 implBuildFromRelative( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year ); 318 } 319 // ----------------------------------------------------------------------- subDays(sal_Int32 nDays,Date & _rDate)320 static void subDays( sal_Int32 nDays, Date& _rDate ) 321 { 322 sal_Int32 nTempDays = implRelativeToAbsoluteNull( _rDate ); 323 324 nTempDays -= nDays; 325 if ( nTempDays > MAX_DAYS ) 326 { 327 _rDate.Day = 31; 328 _rDate.Month = 12; 329 _rDate.Year = 9999; 330 } 331 else if ( nTempDays <= 0 ) 332 { 333 _rDate.Day = 1; 334 _rDate.Month = 1; 335 _rDate.Year = 00; 336 } 337 else 338 implBuildFromRelative( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year ); 339 } 340 // ------------------------------------------------------------------------- toDate(double dVal,const Date & _rNullDate)341 Date DBTypeConversion::toDate(double dVal, const Date& _rNullDate) 342 { 343 Date aRet = _rNullDate; 344 345 if (dVal >= 0) 346 addDays((sal_Int32)dVal,aRet); 347 else 348 subDays((sal_uInt32)(-dVal),aRet); 349 // x -= (sal_uInt32)(-nDays); 350 351 return aRet; 352 } 353 // ------------------------------------------------------------------------- toTime(double dVal)354 Time DBTypeConversion::toTime(double dVal) 355 { 356 sal_Int32 nDays = (sal_Int32)dVal; 357 sal_Int32 nMS = sal_Int32((dVal - (double)nDays) * fMilliSecondsPerDay + 0.5); 358 359 sal_Int16 nSign; 360 if ( nMS < 0 ) 361 { 362 nMS *= -1; 363 nSign = -1; 364 } 365 else 366 nSign = 1; 367 368 Time xRet; 369 // Zeit normalisieren 370 // we have to sal_Int32 here because otherwise we get an overflow 371 sal_Int32 nHundredthSeconds = nMS/10; 372 sal_Int32 nSeconds = nHundredthSeconds / 100; 373 sal_Int32 nMinutes = nSeconds / 60; 374 375 xRet.HundredthSeconds = (sal_uInt16)(nHundredthSeconds % 100); 376 xRet.Seconds = (sal_uInt16)(nSeconds % 60); 377 xRet.Hours = (sal_uInt16)(nMinutes / 60); 378 xRet.Minutes = (sal_uInt16)(nMinutes % 60); 379 380 // Zeit zusammenbauen 381 sal_Int32 nTime = (sal_Int32)(xRet.HundredthSeconds + (xRet.Seconds*100) + (xRet.Minutes*10000) + (xRet.Hours*1000000)) * nSign; 382 383 if(nTime < 0) 384 { 385 xRet.HundredthSeconds = 99; 386 xRet.Minutes = 59; 387 xRet.Seconds = 59; 388 xRet.Hours = 23; 389 } 390 return xRet; 391 } 392 //------------------------------------------------------------------------------ toDateTime(double dVal,const Date & _rNullDate)393 DateTime DBTypeConversion::toDateTime(double dVal, const Date& _rNullDate) 394 { 395 Date aDate = toDate(dVal, _rNullDate); 396 Time aTime = toTime(dVal); 397 398 DateTime xRet; 399 400 xRet.Day = aDate.Day; 401 xRet.Month = aDate.Month; 402 xRet.Year = aDate.Year; 403 404 xRet.HundredthSeconds = aTime.HundredthSeconds; 405 xRet.Minutes = aTime.Minutes; 406 xRet.Seconds = aTime.Seconds; 407 xRet.Hours = aTime.Hours; 408 409 410 return xRet; 411 } 412 //------------------------------------------------------------------------------ toDate(const::rtl::OUString & _sSQLString)413 Date DBTypeConversion::toDate(const ::rtl::OUString& _sSQLString) 414 { 415 // get the token out of a string 416 static sal_Unicode sDateSep = '-'; 417 418 sal_Int32 nIndex = 0; 419 sal_uInt16 nYear = 0, 420 nMonth = 0, 421 nDay = 0; 422 nYear = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32(); 423 if(nIndex != -1) 424 { 425 nMonth = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32(); 426 if(nIndex != -1) 427 nDay = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32(); 428 } 429 430 return Date(nDay,nMonth,nYear); 431 } 432 433 //----------------------------------------------------------------------------- toDateTime(const::rtl::OUString & _sSQLString)434 DateTime DBTypeConversion::toDateTime(const ::rtl::OUString& _sSQLString) 435 { 436 //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Timestamp.html#valueOf(java.lang.String) 437 //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Date.html#valueOf(java.lang.String) 438 //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Time.html#valueOf(java.lang.String) 439 440 // the date part 441 Date aDate = toDate(_sSQLString); 442 Time aTime; 443 sal_Int32 nSeparation = _sSQLString.indexOf( ' ' ); 444 if ( -1 != nSeparation ) 445 aTime = toTime( _sSQLString.copy( nSeparation ) ); 446 447 return DateTime(aTime.HundredthSeconds,aTime.Seconds,aTime.Minutes,aTime.Hours,aDate.Day,aDate.Month,aDate.Year); 448 } 449 450 //----------------------------------------------------------------------------- toTime(const::rtl::OUString & _sSQLString)451 Time DBTypeConversion::toTime(const ::rtl::OUString& _sSQLString) 452 { 453 static sal_Unicode sTimeSep = ':'; 454 455 sal_Int32 nIndex = 0; 456 sal_uInt16 nHour = 0, 457 nMinute = 0, 458 nSecond = 0, 459 nHundredthSeconds = 0; 460 nHour = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32(); 461 if(nIndex != -1) 462 { 463 nMinute = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32(); 464 if(nIndex != -1) 465 { 466 nSecond = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32(); 467 nIndex = 0; 468 ::rtl::OUString sNano(_sSQLString.getToken(1,'.',nIndex)); 469 if ( sNano.getLength() ) 470 { 471 // our time struct only supports hundredth seconds 472 sNano = sNano.copy(0,::std::min<sal_Int32>(sNano.getLength(),2)); 473 const static ::rtl::OUString s_Zeros(RTL_CONSTASCII_USTRINGPARAM("00")); 474 sNano += s_Zeros.copy(0,s_Zeros.getLength() - sNano.getLength()); 475 nHundredthSeconds = static_cast<sal_uInt16>(sNano.toInt32()); 476 } 477 } 478 } 479 return Time(nHundredthSeconds,nSecond,nMinute,nHour); 480 } 481 482 //......................................................................... 483 } // namespace dbtools 484 //......................................................................... 485 486 487