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