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
CalendarWrapper(const Reference<lang::XMultiServiceFactory> & xSF)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
~CalendarWrapper()104 CalendarWrapper::~CalendarWrapper()
105 {
106 }
107
108
loadDefaultCalendar(const::com::sun::star::lang::Locale & rLocale)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
loadCalendar(const::rtl::OUString & rUniqueID,const::com::sun::star::lang::Locale & rLocale)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
getLoadedCalendar() const154 ::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
getAllCalendars(const::com::sun::star::lang::Locale & rLocale) const175 ::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
getUniqueID() const196 ::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
setDateTime(double nTimeInDays)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
getDateTime() const237 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
getCombinedOffsetInMillis(sal_Int16 nParentFieldIndex,sal_Int16 nChildFieldIndex) const258 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
getZoneOffsetInMillis() const288 sal_Int32 CalendarWrapper::getZoneOffsetInMillis() const
289 {
290 return getCombinedOffsetInMillis( CalendarFieldIndex::ZONE_OFFSET,
291 CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS);
292 }
293
294
getDSTOffsetInMillis() const295 sal_Int32 CalendarWrapper::getDSTOffsetInMillis() const
296 {
297 return getCombinedOffsetInMillis( CalendarFieldIndex::DST_OFFSET,
298 CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS);
299 }
300
301
setLocalDateTime(double nTimeInDays)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
getLocalDateTime() const359 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
setValue(sal_Int16 nFieldIndex,sal_Int16 nValue)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
isValid() const406 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
getValue(sal_Int16 nFieldIndex) const427 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
addValue(sal_Int16 nFieldIndex,sal_Int32 nAmount)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
getFirstDayOfWeek() const468 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
setFirstDayOfWeek(sal_Int16 nDay)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
setMinimumNumberOfDaysForFirstWeek(sal_Int16 nDays)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
getMinimumNumberOfDaysForFirstWeek() const529 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
getNumberOfMonthsInYear() const550 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
getNumberOfDaysInWeek() const571 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
getMonths() const592 ::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
getDays() const613 ::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
getDisplayName(sal_Int16 nCalendarDisplayIndex,sal_Int16 nIdx,sal_Int16 nNameType) const634 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
getDisplayString(sal_Int32 nCalendarDisplayCode,sal_Int16 nNativeNumberMode) const657 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