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_unotools.hxx" 30 31 #include <unotools/calendarwrapper.hxx> 32 #include <tools/string.hxx> 33 #include <tools/debug.hxx> 34 35 #ifndef _COMPHELPER_COMPONENTFACTORY_HXX_ 36 #include <comphelper/componentfactory.hxx> 37 #endif 38 #include <com/sun/star/i18n/CalendarFieldIndex.hpp> 39 #include <com/sun/star/i18n/XExtendedCalendar.hpp> 40 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 41 42 #define CALENDAR_LIBRARYNAME "i18n" 43 #define CALENDAR_SERVICENAME "com.sun.star.i18n.LocaleCalendar" 44 45 46 using namespace ::com::sun::star; 47 using namespace ::com::sun::star::i18n; 48 using namespace ::com::sun::star::uno; 49 50 51 const double MILLISECONDS_PER_DAY = 1000.0 * 60.0 * 60.0 * 24.0; 52 53 54 CalendarWrapper::CalendarWrapper( 55 const Reference< lang::XMultiServiceFactory > & xSF 56 ) 57 : 58 xSMgr( xSF ), 59 aEpochStart( Date( 1, 1, 1970 ) ) 60 { 61 if ( xSMgr.is() ) 62 { 63 try 64 { 65 xC = Reference< XExtendedCalendar > ( xSMgr->createInstance( 66 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CALENDAR_SERVICENAME ) ) ), 67 uno::UNO_QUERY ); 68 } 69 catch ( Exception& e ) 70 { 71 #ifdef DBG_UTIL 72 ByteString aMsg( "CalendarWrapper ctor: Exception caught\n" ); 73 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 74 DBG_ERRORFILE( aMsg.GetBuffer() ); 75 #else 76 (void)e; 77 #endif 78 } 79 } 80 else 81 { // try to get an instance somehow 82 DBG_ERRORFILE( "CalendarWrapper: no service manager, trying own" ); 83 try 84 { 85 Reference< XInterface > xI = ::comphelper::getComponentInstance( 86 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME( CALENDAR_LIBRARYNAME ) ) ), 87 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CALENDAR_SERVICENAME ) ) ); 88 if ( xI.is() ) 89 { 90 Any x = xI->queryInterface( ::getCppuType((const Reference< XExtendedCalendar >*)0) ); 91 x >>= xC; 92 } 93 } 94 catch ( Exception& e ) 95 { 96 #ifdef DBG_UTIL 97 ByteString aMsg( "getComponentInstance: Exception caught\n" ); 98 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 99 DBG_ERRORFILE( aMsg.GetBuffer() ); 100 #else 101 (void)e; 102 #endif 103 } 104 } 105 } 106 107 108 CalendarWrapper::~CalendarWrapper() 109 { 110 } 111 112 113 void CalendarWrapper::loadDefaultCalendar( const ::com::sun::star::lang::Locale& rLocale ) 114 { 115 try 116 { 117 if ( xC.is() ) 118 xC->loadDefaultCalendar( rLocale ); 119 } 120 catch ( Exception& e ) 121 { 122 #ifdef DBG_UTIL 123 ByteString aMsg( "loadDefaultCalendar: Exception caught\n" ); 124 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 125 DBG_ERRORFILE( aMsg.GetBuffer() ); 126 #else 127 (void)e; 128 #endif 129 } 130 } 131 132 133 void CalendarWrapper::loadCalendar( const ::rtl::OUString& rUniqueID, const ::com::sun::star::lang::Locale& rLocale ) 134 { 135 try 136 { 137 if ( xC.is() ) 138 xC->loadCalendar( rUniqueID, rLocale ); 139 } 140 catch ( Exception& e ) 141 { 142 #ifdef DBG_UTIL 143 ByteString aMsg( "loadCalendar: Exception caught\nrequested: " ); 144 aMsg += ByteString( String( rUniqueID ), RTL_TEXTENCODING_UTF8 ); 145 aMsg += " Locale: "; 146 aMsg += ByteString( String( rLocale.Language ), RTL_TEXTENCODING_UTF8 ); 147 aMsg += '_'; 148 aMsg += ByteString( String( rLocale.Country ), RTL_TEXTENCODING_UTF8 ); 149 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 150 DBG_ERRORFILE( aMsg.GetBuffer() ); 151 #else 152 (void)e; 153 #endif 154 } 155 } 156 157 158 ::com::sun::star::i18n::Calendar CalendarWrapper::getLoadedCalendar() const 159 { 160 try 161 { 162 if ( xC.is() ) 163 return xC->getLoadedCalendar(); 164 } 165 catch ( Exception& e ) 166 { 167 #ifdef DBG_UTIL 168 ByteString aMsg( "getLoadedCalendar: Exception caught\n" ); 169 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 170 DBG_ERRORFILE( aMsg.GetBuffer() ); 171 #else 172 (void)e; 173 #endif 174 } 175 return ::com::sun::star::i18n::Calendar(); 176 } 177 178 179 ::com::sun::star::uno::Sequence< ::rtl::OUString > CalendarWrapper::getAllCalendars( const ::com::sun::star::lang::Locale& rLocale ) const 180 { 181 try 182 { 183 if ( xC.is() ) 184 return xC->getAllCalendars( rLocale ); 185 } 186 catch ( Exception& e ) 187 { 188 #ifdef DBG_UTIL 189 ByteString aMsg( "getAllCalendars: Exception caught\n" ); 190 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 191 DBG_ERRORFILE( aMsg.GetBuffer() ); 192 #else 193 (void)e; 194 #endif 195 } 196 return ::com::sun::star::uno::Sequence< ::rtl::OUString > (0); 197 } 198 199 200 ::rtl::OUString CalendarWrapper::getUniqueID() const 201 { 202 try 203 { 204 if ( xC.is() ) 205 return xC->getUniqueID(); 206 } 207 catch ( Exception& e ) 208 { 209 #ifdef DBG_UTIL 210 ByteString aMsg( "getUniqueID: Exception caught\n" ); 211 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 212 DBG_ERRORFILE( aMsg.GetBuffer() ); 213 #else 214 (void)e; 215 #endif 216 } 217 return ::rtl::OUString(); 218 } 219 220 221 void CalendarWrapper::setDateTime( double nTimeInDays ) 222 { 223 try 224 { 225 if ( xC.is() ) 226 xC->setDateTime( nTimeInDays ); 227 } 228 catch ( Exception& e ) 229 { 230 #ifdef DBG_UTIL 231 ByteString aMsg( "setDateTime: Exception caught\n" ); 232 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 233 DBG_ERRORFILE( aMsg.GetBuffer() ); 234 #else 235 (void)e; 236 #endif 237 } 238 } 239 240 241 double CalendarWrapper::getDateTime() const 242 { 243 try 244 { 245 if ( xC.is() ) 246 return xC->getDateTime(); 247 } 248 catch ( Exception& e ) 249 { 250 #ifdef DBG_UTIL 251 ByteString aMsg( "getDateTime: Exception caught\n" ); 252 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 253 DBG_ERRORFILE( aMsg.GetBuffer() ); 254 #else 255 (void)e; 256 #endif 257 } 258 return 0.0; 259 } 260 261 262 sal_Int32 CalendarWrapper::getCombinedOffsetInMillis( 263 sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex ) const 264 { 265 sal_Int32 nOffset = 0; 266 try 267 { 268 if ( xC.is() ) 269 { 270 nOffset = static_cast<sal_Int32>( xC->getValue( nParentFieldIndex )) * 60000; 271 sal_Int16 nSecondMillis = xC->getValue( nChildFieldIndex ); 272 if (nOffset < 0) 273 nOffset -= static_cast<sal_uInt16>( nSecondMillis); 274 else 275 nOffset += static_cast<sal_uInt16>( nSecondMillis); 276 } 277 } 278 catch ( Exception& e ) 279 { 280 #ifdef DBG_UTIL 281 ByteString aMsg( "setLocalDateTime: Exception caught\n" ); 282 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 283 DBG_ERRORFILE( aMsg.GetBuffer() ); 284 #else 285 (void)e; 286 #endif 287 } 288 return nOffset; 289 } 290 291 292 sal_Int32 CalendarWrapper::getZoneOffsetInMillis() const 293 { 294 return getCombinedOffsetInMillis( CalendarFieldIndex::ZONE_OFFSET, 295 CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS); 296 } 297 298 299 sal_Int32 CalendarWrapper::getDSTOffsetInMillis() const 300 { 301 return getCombinedOffsetInMillis( CalendarFieldIndex::DST_OFFSET, 302 CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS); 303 } 304 305 306 void CalendarWrapper::setLocalDateTime( double nTimeInDays ) 307 { 308 try 309 { 310 if ( xC.is() ) 311 { 312 // First set a nearby value to obtain the timezone and DST offset. 313 // This is necessary to let ICU choose the corresponding 314 // OlsonTimeZone transitions. Since ICU incorporates also 315 // historical data even the timezone may differ for different 316 // dates! (Which was the cause for #i76623# when the timezone of a 317 // previously set date was used.) Timezone may also include 318 // seconds, so use milliseconds field as well. 319 xC->setDateTime( nTimeInDays ); 320 sal_Int32 nZone1 = getZoneOffsetInMillis(); 321 sal_Int32 nDST1 = getDSTOffsetInMillis(); 322 double nLoc = nTimeInDays - (double)(nZone1 + nDST1) / MILLISECONDS_PER_DAY; 323 xC->setDateTime( nLoc ); 324 sal_Int32 nZone2 = getZoneOffsetInMillis(); 325 sal_Int32 nDST2 = getDSTOffsetInMillis(); 326 // If DSTs differ after calculation, we crossed boundaries. Do it 327 // again, this time using the DST corrected initial value for the 328 // real local time. 329 // See also localtime/gmtime conversion pitfalls at 330 // http://www.erack.de/download/timetest.c 331 if ( nDST1 != nDST2 ) 332 { 333 nLoc = nTimeInDays - (double)(nZone2 + nDST2) / MILLISECONDS_PER_DAY; 334 xC->setDateTime( nLoc ); 335 // #i17222# If the DST onset rule says to switch from 00:00 to 336 // 01:00 and we tried to set onsetDay 00:00 with DST, the 337 // result was onsetDay-1 23:00 and no DST, which is not what we 338 // want. So once again without DST, resulting in onsetDay 339 // 01:00 and DST. Yes, this seems to be weird, but logically 340 // correct. 341 sal_Int32 nDST3 = getDSTOffsetInMillis(); 342 if ( nDST2 != nDST3 && !nDST3 ) 343 { 344 nLoc = nTimeInDays - (double)(nZone2 + nDST3) / MILLISECONDS_PER_DAY; 345 xC->setDateTime( nLoc ); 346 } 347 } 348 } 349 } 350 catch ( Exception& e ) 351 { 352 #ifdef DBG_UTIL 353 ByteString aMsg( "setLocalDateTime: Exception caught\n" ); 354 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 355 DBG_ERRORFILE( aMsg.GetBuffer() ); 356 #else 357 (void)e; 358 #endif 359 } 360 } 361 362 363 double CalendarWrapper::getLocalDateTime() const 364 { 365 try 366 { 367 if ( xC.is() ) 368 { 369 double nTimeInDays = xC->getDateTime(); 370 sal_Int32 nZone = getZoneOffsetInMillis(); 371 sal_Int32 nDST = getDSTOffsetInMillis(); 372 nTimeInDays += (double)(nZone + nDST) / MILLISECONDS_PER_DAY; 373 return nTimeInDays; 374 } 375 } 376 catch ( Exception& e ) 377 { 378 #ifdef DBG_UTIL 379 ByteString aMsg( "getLocalDateTime: Exception caught\n" ); 380 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 381 DBG_ERRORFILE( aMsg.GetBuffer() ); 382 #else 383 (void)e; 384 #endif 385 } 386 return 0.0; 387 } 388 389 390 void CalendarWrapper::setValue( sal_Int16 nFieldIndex, sal_Int16 nValue ) 391 { 392 try 393 { 394 if ( xC.is() ) 395 xC->setValue( nFieldIndex, nValue ); 396 } 397 catch ( Exception& e ) 398 { 399 #ifdef DBG_UTIL 400 ByteString aMsg( "setValue: Exception caught\n" ); 401 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 402 DBG_ERRORFILE( aMsg.GetBuffer() ); 403 #else 404 (void)e; 405 #endif 406 } 407 } 408 409 410 sal_Bool CalendarWrapper::isValid() const 411 { 412 try 413 { 414 if ( xC.is() ) 415 return xC->isValid(); 416 } 417 catch ( Exception& e ) 418 { 419 #ifdef DBG_UTIL 420 ByteString aMsg( "isValid: Exception caught\n" ); 421 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 422 DBG_ERRORFILE( aMsg.GetBuffer() ); 423 #else 424 (void)e; 425 #endif 426 } 427 return sal_False; 428 } 429 430 431 sal_Int16 CalendarWrapper::getValue( sal_Int16 nFieldIndex ) const 432 { 433 try 434 { 435 if ( xC.is() ) 436 return xC->getValue( nFieldIndex ); 437 } 438 catch ( Exception& e ) 439 { 440 #ifdef DBG_UTIL 441 ByteString aMsg( "getValue: Exception caught\n" ); 442 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 443 DBG_ERRORFILE( aMsg.GetBuffer() ); 444 #else 445 (void)e; 446 #endif 447 } 448 return 0; 449 } 450 451 452 void CalendarWrapper::addValue( sal_Int16 nFieldIndex, sal_Int32 nAmount ) 453 { 454 try 455 { 456 if ( xC.is() ) 457 xC->addValue( nFieldIndex, nAmount ); 458 } 459 catch ( Exception& e ) 460 { 461 #ifdef DBG_UTIL 462 ByteString aMsg( "addValue: Exception caught\n" ); 463 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 464 DBG_ERRORFILE( aMsg.GetBuffer() ); 465 #else 466 (void)e; 467 #endif 468 } 469 } 470 471 472 sal_Int16 CalendarWrapper::getFirstDayOfWeek() const 473 { 474 try 475 { 476 if ( xC.is() ) 477 return xC->getFirstDayOfWeek(); 478 } 479 catch ( Exception& e ) 480 { 481 #ifdef DBG_UTIL 482 ByteString aMsg( "getFirstDayOfWeek: Exception caught\n" ); 483 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 484 DBG_ERRORFILE( aMsg.GetBuffer() ); 485 #else 486 (void)e; 487 #endif 488 } 489 return 0; 490 } 491 492 493 void CalendarWrapper::setFirstDayOfWeek( sal_Int16 nDay ) 494 { 495 try 496 { 497 if ( xC.is() ) 498 xC->setFirstDayOfWeek( nDay ); 499 } 500 catch ( Exception& e ) 501 { 502 #ifdef DBG_UTIL 503 ByteString aMsg( "setFirstDayOfWeek: Exception caught\n" ); 504 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 505 DBG_ERRORFILE( aMsg.GetBuffer() ); 506 #else 507 (void)e; 508 #endif 509 } 510 } 511 512 513 void CalendarWrapper::setMinimumNumberOfDaysForFirstWeek( sal_Int16 nDays ) 514 { 515 try 516 { 517 if ( xC.is() ) 518 xC->setMinimumNumberOfDaysForFirstWeek( nDays ); 519 } 520 catch ( Exception& e ) 521 { 522 #ifdef DBG_UTIL 523 ByteString aMsg( "setMinimumNumberOfDaysForFirstWeek: Exception caught\n" ); 524 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 525 DBG_ERRORFILE( aMsg.GetBuffer() ); 526 #else 527 (void)e; 528 #endif 529 } 530 } 531 532 533 sal_Int16 CalendarWrapper::getMinimumNumberOfDaysForFirstWeek() const 534 { 535 try 536 { 537 if ( xC.is() ) 538 return xC->getMinimumNumberOfDaysForFirstWeek(); 539 } 540 catch ( Exception& e ) 541 { 542 #ifdef DBG_UTIL 543 ByteString aMsg( "getMinimumNumberOfDaysForFirstWeek: Exception caught\n" ); 544 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 545 DBG_ERRORFILE( aMsg.GetBuffer() ); 546 #else 547 (void)e; 548 #endif 549 } 550 return 0; 551 } 552 553 554 sal_Int16 CalendarWrapper::getNumberOfMonthsInYear() const 555 { 556 try 557 { 558 if ( xC.is() ) 559 return xC->getNumberOfMonthsInYear(); 560 } 561 catch ( Exception& e ) 562 { 563 #ifdef DBG_UTIL 564 ByteString aMsg( "getNumberOfMonthsInYear: Exception caught\n" ); 565 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 566 DBG_ERRORFILE( aMsg.GetBuffer() ); 567 #else 568 (void)e; 569 #endif 570 } 571 return 0; 572 } 573 574 575 sal_Int16 CalendarWrapper::getNumberOfDaysInWeek() const 576 { 577 try 578 { 579 if ( xC.is() ) 580 return xC->getNumberOfDaysInWeek(); 581 } 582 catch ( Exception& e ) 583 { 584 #ifdef DBG_UTIL 585 ByteString aMsg( "getNumberOfDaysInWeek: Exception caught\n" ); 586 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 587 DBG_ERRORFILE( aMsg.GetBuffer() ); 588 #else 589 (void)e; 590 #endif 591 } 592 return 0; 593 } 594 595 596 ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > CalendarWrapper::getMonths() const 597 { 598 try 599 { 600 if ( xC.is() ) 601 return xC->getMonths(); 602 } 603 catch ( Exception& e ) 604 { 605 #ifdef DBG_UTIL 606 ByteString aMsg( "getMonths: Exception caught\n" ); 607 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 608 DBG_ERRORFILE( aMsg.GetBuffer() ); 609 #else 610 (void)e; 611 #endif 612 } 613 return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > (0); 614 } 615 616 617 ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > CalendarWrapper::getDays() const 618 { 619 try 620 { 621 if ( xC.is() ) 622 return xC->getDays(); 623 } 624 catch ( Exception& e ) 625 { 626 #ifdef DBG_UTIL 627 ByteString aMsg( "getDays: Exception caught\n" ); 628 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 629 DBG_ERRORFILE( aMsg.GetBuffer() ); 630 #else 631 (void)e; 632 #endif 633 } 634 return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > (0); 635 } 636 637 638 String CalendarWrapper::getDisplayName( sal_Int16 nCalendarDisplayIndex, sal_Int16 nIdx, sal_Int16 nNameType ) const 639 { 640 try 641 { 642 if ( xC.is() ) 643 return xC->getDisplayName( nCalendarDisplayIndex, nIdx, nNameType ); 644 } 645 catch ( Exception& e ) 646 { 647 #ifdef DBG_UTIL 648 ByteString aMsg( "getDisplayName: Exception caught\n" ); 649 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 650 DBG_ERRORFILE( aMsg.GetBuffer() ); 651 #else 652 (void)e; 653 #endif 654 } 655 return String(); 656 } 657 658 659 // --- XExtendedCalendar ----------------------------------------------------- 660 661 String CalendarWrapper::getDisplayString( sal_Int32 nCalendarDisplayCode, sal_Int16 nNativeNumberMode ) const 662 { 663 try 664 { 665 if ( xC.is() ) 666 return xC->getDisplayString( nCalendarDisplayCode, nNativeNumberMode ); 667 } 668 catch ( Exception& e ) 669 { 670 #ifdef DBG_UTIL 671 ByteString aMsg( "getDisplayString: Exception caught\n" ); 672 aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 ); 673 DBG_ERRORFILE( aMsg.GetBuffer() ); 674 #else 675 (void)e; 676 #endif 677 } 678 return String(); 679 } 680 681