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