1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 //------------------------------------------------------------------
22 // date functions add in
24 //------------------------------------------------------------------
26 #include "datefunc.hxx"
27 #include "datefunc.hrc"
28 #include <cppuhelper/factory.hxx>
29 #include <osl/diagnose.h>
30 #include <rtl/ustrbuf.hxx>
31 #include <tools/resmgr.hxx>
32 #include <tools/rcid.h>
33 #include <com/sun/star/util/Date.hpp>
35 using namespace ::com::sun::star
;
36 using namespace ::rtl
;
38 //------------------------------------------------------------------
40 #define ADDIN_SERVICE "com.sun.star.sheet.AddIn"
41 #define MY_SERVICE "com.sun.star.sheet.addin.DateFunctions"
42 #define MY_IMPLNAME "com.sun.star.sheet.addin.DateFunctionsImpl"
44 //------------------------------------------------------------------
46 #define STR_FROM_ANSI( s ) OUString( s, strlen( s ), RTL_TEXTENCODING_MS_1252 )
48 //------------------------------------------------------------------
50 const sal_uInt32
ScaList::nStartSize
= 16;
51 const sal_uInt32
ScaList::nIncrSize
= 16;
54 pData( new void*[ nStartSize
] ),
70 void** pNewData
= new void*[ nSize
];
71 memcpy( pNewData
, pData
, nCount
* sizeof( void* ) );
77 //------------------------------------------------------------------
79 ScaStringList::~ScaStringList()
81 for( OUString
* pStr
= First(); pStr
; pStr
= Next() )
85 //------------------------------------------------------------------
87 ScaResId::ScaResId( sal_uInt16 nId
, ResMgr
& rResMgr
) :
93 //------------------------------------------------------------------
95 #define UNIQUE sal_False // function name does not exist in Calc
97 #define STDPAR sal_False // all parameters are described
98 #define INTPAR sal_True // first parameter is internal
100 #define FUNCDATA( FuncName, ParamCount, Category, Double, IntPar ) \
101 { "get" #FuncName, DATE_FUNCNAME_##FuncName, DATE_FUNCDESC_##FuncName, DATE_DEFFUNCNAME_##FuncName, ParamCount, Category, Double, IntPar }
103 const ScaFuncDataBase pFuncDataArr
[] =
105 FUNCDATA( DiffWeeks
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
106 FUNCDATA( DiffMonths
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
107 FUNCDATA( DiffYears
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
108 FUNCDATA( IsLeapYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
109 FUNCDATA( DaysInMonth
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
110 FUNCDATA( DaysInYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
111 FUNCDATA( WeeksInYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
112 FUNCDATA( Rot13
, 1, ScaCat_Text
, UNIQUE
, STDPAR
)
118 //------------------------------------------------------------------
120 ScaFuncData::ScaFuncData( const ScaFuncDataBase
& rBaseData
, ResMgr
& rResMgr
) :
121 aIntName( OUString::createFromAscii( rBaseData
.pIntName
) ),
122 nUINameID( rBaseData
.nUINameID
),
123 nDescrID( rBaseData
.nDescrID
),
124 nCompListID( rBaseData
.nCompListID
),
125 nParamCount( rBaseData
.nParamCount
),
126 eCat( rBaseData
.eCat
),
127 bDouble( rBaseData
.bDouble
),
128 bWithOpt( rBaseData
.bWithOpt
)
130 ScaResStringArrLoader
aArrLoader( RID_DATE_DEFFUNCTION_NAMES
, nCompListID
, rResMgr
);
131 const ResStringArray
& rArr
= aArrLoader
.GetStringArray();
133 for( sal_uInt16 nIndex
= 0; nIndex
< rArr
.Count(); nIndex
++ )
134 aCompList
.Append( rArr
.GetString( nIndex
) );
137 ScaFuncData::~ScaFuncData()
141 sal_uInt16
ScaFuncData::GetStrIndex( sal_uInt16 nParam
) const
145 return (nParam
> nParamCount
) ? (nParamCount
* 2) : (nParam
* 2);
149 //------------------------------------------------------------------
151 ScaFuncDataList::ScaFuncDataList( ResMgr
& rResMgr
) :
154 for( sal_uInt16 nIndex
= 0; nIndex
< SAL_N_ELEMENTS(pFuncDataArr
); nIndex
++ )
155 Append( new ScaFuncData( pFuncDataArr
[ nIndex
], rResMgr
) );
158 ScaFuncDataList::~ScaFuncDataList()
160 for( ScaFuncData
* pFData
= First(); pFData
; pFData
= Next() )
164 const ScaFuncData
* ScaFuncDataList::Get( const OUString
& rProgrammaticName
) const
166 if( aLastName
== rProgrammaticName
)
169 for( sal_uInt32 nIndex
= 0; nIndex
< Count(); nIndex
++ )
171 const ScaFuncData
* pCurr
= Get( nIndex
);
172 if( pCurr
->Is( rProgrammaticName
) )
174 const_cast< ScaFuncDataList
* >( this )->aLastName
= rProgrammaticName
;
175 const_cast< ScaFuncDataList
* >( this )->nLast
= nIndex
;
183 //------------------------------------------------------------------
185 ScaFuncRes::ScaFuncRes( ResId
& rResId
, ResMgr
& rResMgr
, sal_uInt16 nIndex
, OUString
& rRet
) :
188 rRet
= String( ScaResId( nIndex
, rResMgr
) );
193 //------------------------------------------------------------------
195 // entry points for service registration / instantiation
197 //------------------------------------------------------------------
199 uno::Reference
< uno::XInterface
> SAL_CALL
ScaDateAddIn_CreateInstance(
200 const uno::Reference
< lang::XMultiServiceFactory
>& )
202 static uno::Reference
< uno::XInterface
> xInst
= (cppu::OWeakObject
*) new ScaDateAddIn();
207 //------------------------------------------------------------------------
211 SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
date_component_getFactory(
212 const sal_Char
* pImplName
, void * pServiceManager
, void * /*pRegistryKey*/ )
216 if ( pServiceManager
&&
217 OUString::createFromAscii( pImplName
) == ScaDateAddIn::getImplementationName_Static() )
219 uno::Reference
< lang::XSingleServiceFactory
> xFactory( cppu::createOneInstanceFactory(
220 reinterpret_cast< lang::XMultiServiceFactory
* >( pServiceManager
),
221 ScaDateAddIn::getImplementationName_Static(),
222 ScaDateAddIn_CreateInstance
,
223 ScaDateAddIn::getSupportedServiceNames_Static() ) );
228 pRet
= xFactory
.get();
237 //------------------------------------------------------------------------
239 // "normal" service implementation
241 //------------------------------------------------------------------------
243 ScaDateAddIn::ScaDateAddIn() :
246 pFuncDataList( NULL
)
250 ScaDateAddIn::~ScaDateAddIn()
253 delete pFuncDataList
;
255 delete[] pDefLocales
;
257 // pResMgr already deleted (_all_ resource managers are deleted _before_ this dtor is called)
260 static const sal_Char
* pLang
[] = { "de", "en" };
261 static const sal_Char
* pCoun
[] = { "DE", "US" };
262 static const sal_uInt32 nNumOfLoc
= SAL_N_ELEMENTS( pLang
);
264 void ScaDateAddIn::InitDefLocales()
266 pDefLocales
= new lang::Locale
[ nNumOfLoc
];
268 for( sal_uInt32 nIndex
= 0; nIndex
< nNumOfLoc
; nIndex
++ )
270 pDefLocales
[ nIndex
].Language
= OUString::createFromAscii( pLang
[ nIndex
] );
271 pDefLocales
[ nIndex
].Country
= OUString::createFromAscii( pCoun
[ nIndex
] );
275 const lang::Locale
& ScaDateAddIn::GetLocale( sal_uInt32 nIndex
)
280 return (nIndex
< sizeof( pLang
)) ? pDefLocales
[ nIndex
] : aFuncLoc
;
283 ResMgr
& ScaDateAddIn::GetResMgr() throw( uno::RuntimeException
)
287 InitData(); // try to get resource manager
289 throw uno::RuntimeException();
294 void ScaDateAddIn::InitData()
299 OString
aModName( "date" );
300 pResMgr
= ResMgr::CreateResMgr( aModName
.getStr(), LanguageTag( aFuncLoc
) );
303 delete pFuncDataList
;
305 pFuncDataList
= pResMgr
? new ScaFuncDataList( *pResMgr
) : NULL
;
314 OUString
ScaDateAddIn::GetDisplFuncStr( sal_uInt16 nResId
) throw( uno::RuntimeException
)
316 return ScaResStringLoader( RID_DATE_FUNCTION_NAMES
, nResId
, GetResMgr() ).GetString();
319 OUString
ScaDateAddIn::GetFuncDescrStr( sal_uInt16 nResId
, sal_uInt16 nStrIndex
) throw( uno::RuntimeException
)
323 ScaResPublisher
aResPubl( ScaResId( RID_DATE_FUNCTION_DESCRIPTIONS
, GetResMgr() ) );
324 ScaResId
aResId( nResId
, GetResMgr() );
325 aResId
.SetRT( RSC_RESOURCE
);
327 if( aResPubl
.IsAvailableRes( aResId
) )
328 ScaFuncRes
aSubRes( aResId
, GetResMgr(), nStrIndex
, aRet
);
330 aResPubl
.FreeResource();
335 //------------------------------------------------------------------------
337 OUString
ScaDateAddIn::getImplementationName_Static()
339 return OUString( MY_IMPLNAME
);
342 uno::Sequence
< OUString
> ScaDateAddIn::getSupportedServiceNames_Static()
344 uno::Sequence
< OUString
> aRet( 2 );
345 OUString
* pArray
= aRet
.getArray();
346 pArray
[0] = OUString( ADDIN_SERVICE
);
347 pArray
[1] = OUString( MY_SERVICE
);
353 OUString SAL_CALL
ScaDateAddIn::getServiceName() throw( uno::RuntimeException
)
355 // name of specific AddIn service
356 return OUString( MY_SERVICE
);
361 OUString SAL_CALL
ScaDateAddIn::getImplementationName() throw( uno::RuntimeException
)
363 return getImplementationName_Static();
366 sal_Bool SAL_CALL
ScaDateAddIn::supportsService( const OUString
& aServiceName
) throw( uno::RuntimeException
)
368 return aServiceName
== ADDIN_SERVICE
|| aServiceName
== MY_SERVICE
;
371 uno::Sequence
< OUString
> SAL_CALL
ScaDateAddIn::getSupportedServiceNames() throw( uno::RuntimeException
)
373 return getSupportedServiceNames_Static();
378 void SAL_CALL
ScaDateAddIn::setLocale( const lang::Locale
& eLocale
) throw( uno::RuntimeException
)
381 InitData(); // change of locale invalidates resources!
384 lang::Locale SAL_CALL
ScaDateAddIn::getLocale() throw( uno::RuntimeException
)
389 //------------------------------------------------------------------
391 // function descriptions start here
393 //------------------------------------------------------------------
397 OUString SAL_CALL
ScaDateAddIn::getProgrammaticFuntionName( const OUString
& ) throw( uno::RuntimeException
)
400 // (but should be implemented for other uses of the AddIn service)
404 OUString SAL_CALL
ScaDateAddIn::getDisplayFunctionName( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
408 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
411 aRet
= GetDisplFuncStr( pFData
->GetUINameID() );
412 if( pFData
->IsDouble() )
413 aRet
+= STR_FROM_ANSI( "_ADD" );
417 aRet
= STR_FROM_ANSI( "UNKNOWNFUNC_" );
418 aRet
+= aProgrammaticName
;
424 OUString SAL_CALL
ScaDateAddIn::getFunctionDescription( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
428 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
430 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), 1 );
435 OUString SAL_CALL
ScaDateAddIn::getDisplayArgumentName(
436 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
)
440 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
441 if( pFData
&& (nArgument
<= 0xFFFF) )
443 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
445 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
);
447 aRet
= STR_FROM_ANSI( "internal" );
453 OUString SAL_CALL
ScaDateAddIn::getArgumentDescription(
454 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
)
458 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
459 if( pFData
&& (nArgument
<= 0xFFFF) )
461 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
463 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
+ 1 );
465 aRet
= STR_FROM_ANSI( "for internal use only" );
471 OUString SAL_CALL
ScaDateAddIn::getProgrammaticCategoryName(
472 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
476 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
479 switch( pFData
->GetCategory() )
481 case ScaCat_DateTime
: aRet
= STR_FROM_ANSI( "Date&Time" ); break;
482 case ScaCat_Text
: aRet
= STR_FROM_ANSI( "Text" ); break;
483 case ScaCat_Finance
: aRet
= STR_FROM_ANSI( "Financial" ); break;
484 case ScaCat_Inf
: aRet
= STR_FROM_ANSI( "Information" ); break;
485 case ScaCat_Math
: aRet
= STR_FROM_ANSI( "Mathematical" ); break;
486 case ScaCat_Tech
: aRet
= STR_FROM_ANSI( "Technical" ); break;
487 default: // to prevent compiler warnings
493 aRet
= STR_FROM_ANSI( "Add-In" );
497 OUString SAL_CALL
ScaDateAddIn::getDisplayCategoryName(
498 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
500 return getProgrammaticCategoryName( aProgrammaticName
);
504 // XCompatibilityNames
506 uno::Sequence
< sheet::LocalizedName
> SAL_CALL
ScaDateAddIn::getCompatibilityNames(
507 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
509 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
511 return uno::Sequence
< sheet::LocalizedName
>( 0 );
513 const ScaStringList
& rStrList
= pFData
->GetCompNameList();
514 sal_uInt32 nCount
= rStrList
.Count();
516 uno::Sequence
< sheet::LocalizedName
> aRet( nCount
);
517 sheet::LocalizedName
* pArray
= aRet
.getArray();
519 for( sal_uInt32 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
520 pArray
[ nIndex
] = sheet::LocalizedName( GetLocale( nIndex
), *rStrList
.Get( nIndex
) );
526 // auxiliary functions
528 sal_Bool
IsLeapYear( sal_uInt16 nYear
)
530 return ((((nYear
% 4) == 0) && ((nYear
% 100) != 0)) || ((nYear
% 400) == 0));
533 sal_uInt16
DaysInMonth( sal_uInt16 nMonth
, sal_uInt16 nYear
)
535 static sal_uInt16 aDaysInMonth
[12] = { 31, 28, 31, 30, 31, 30,
536 31, 31, 30, 31, 30, 31 };
539 return aDaysInMonth
[nMonth
-1];
542 if ( IsLeapYear(nYear
) )
543 return aDaysInMonth
[nMonth
-1] + 1;
545 return aDaysInMonth
[nMonth
-1];
550 * Convert a date to a count of days starting from 01/01/0001
552 * The internal representation of a Date used in this Addin
553 * is the number of days between 01/01/0001 and the date
554 * this function converts a Day , Month, Year representation
555 * to this internal Date value.
558 sal_Int32
DateToDays( sal_uInt16 nDay
, sal_uInt16 nMonth
, sal_uInt16 nYear
)
560 sal_Int32 nDays
= ((sal_Int32
)nYear
-1) * 365;
561 nDays
+= ((nYear
-1) / 4) - ((nYear
-1) / 100) + ((nYear
-1) / 400);
563 for( sal_uInt16 i
= 1; i
< nMonth
; i
++ )
564 nDays
+= DaysInMonth(i
,nYear
);
571 * Convert a count of days starting from 01/01/0001 to a date
573 * The internal representation of a Date used in this Addin
574 * is the number of days between 01/01/0001 and the date
575 * this function converts this internal Date value
576 * to a Day , Month, Year representation of a Date.
579 void DaysToDate( sal_Int32 nDays
,
580 sal_uInt16
& rDay
, sal_uInt16
& rMonth
, sal_uInt16
& rYear
)
581 throw( lang::IllegalArgumentException
)
584 throw lang::IllegalArgumentException();
593 rYear
= (sal_uInt16
)((nTempDays
/ 365) - i
);
594 nTempDays
-= ((sal_Int32
) rYear
-1) * 365;
595 nTempDays
-= (( rYear
-1) / 4) - (( rYear
-1) / 100) + ((rYear
-1) / 400);
604 if ( nTempDays
> 365 )
606 if ( (nTempDays
!= 366) || !IsLeapYear( rYear
) )
617 while ( (sal_Int32
)nTempDays
> DaysInMonth( rMonth
, rYear
) )
619 nTempDays
-= DaysInMonth( rMonth
, rYear
);
622 rDay
= (sal_uInt16
)nTempDays
;
626 * Get the null date used by the spreadsheet document
628 * The internal representation of a Date used in this Addin
629 * is the number of days between 01/01/0001 and the date
630 * this function returns this internal Date value for the document null date
634 sal_Int32
GetNullDate( const uno::Reference
< beans::XPropertySet
>& xOptions
)
635 throw( uno::RuntimeException
)
641 uno::Any aAny
= xOptions
->getPropertyValue(
642 OUString( "NullDate" ) );
644 if ( aAny
>>= aDate
)
645 return DateToDays( aDate
.Day
, aDate
.Month
, aDate
.Year
);
647 catch (uno::Exception
&)
652 // no null date available -> no calculations possible
653 throw uno::RuntimeException();
660 * Get week difference between 2 dates
662 * new Weeks(date1,date2,mode) function for StarCalc
664 * Two modes of operation are provided.
665 * The first is just a simple division by 7 calculation.
667 * The second calculates the diffence by week of year.
669 * The International Standard IS-8601 has decreed that Monday
670 * shall be the first day of the week.
672 * A week that lies partly in one year and partly in annother
673 * is assigned a number in the year in which most of its days lie.
675 * That means that week 1 of any year is the week that contains the 4. January
677 * The internal representation of a Date used in the Addin is the number of days based on 01/01/0001
679 * A WeekDay can be then calculated by substracting 1 and calculating the rest of
680 * a division by 7, which gives a 0 - 6 value for Monday - Sunday
682 * Using the 4. January rule explained above the formula
684 * nWeek1= ( nDays1 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
686 * calculates a number between 0-53 for each day which is in the same year as nJan4
687 * where 0 means that this week belonged to the year before.
689 * If a day in the same or annother year is used in this formula this calculates
690 * an calendar week offset from a given 4. January
692 * nWeek2 = ( nDays2 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
694 * The 4.January of first Date Argument can thus be used to calculate
695 * the week difference by calendar weeks which is then nWeek = nWeek2 - nWeek1
697 * which can be optimized to
699 * nWeek = ( (nDays2-nJan4+((nJan4-1)%7))/7 ) - ( (nDays1-nJan4+((nJan4-1)%7))/7 )
701 * Note: All calculations are operating on the long integer data type
702 * % is the modulo operator in C which calculates the rest of an Integer division
705 * mode 0 is the interval between the dates in month, that is days / 7
707 * mode 1 is the difference by week of year
711 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffWeeks(
712 const uno::Reference
< beans::XPropertySet
>& xOptions
,
713 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
714 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
716 sal_Int32 nNullDate
= GetNullDate( xOptions
);
718 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
719 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
725 sal_uInt16 nDay
,nMonth
,nYear
;
726 DaysToDate( nDays1
, nDay
, nMonth
, nYear
);
727 sal_Int32 nJan4
= DateToDays( 4, 1, nYear
);
729 nRet
= ( (nDays2
-nJan4
+((nJan4
-1)%7))/7 ) - ( (nDays1
-nJan4
+((nJan4
-1)%7))/7 );
733 nRet
= (nDays2
- nDays1
) / 7;
739 * Get month difference between 2 dates
740 * =Month(start, end, mode) Function for StarCalc
742 * two modes are provided
744 * mode 0 is the interval between the dates in month
746 * mode 1 is the difference in calendar month
749 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffMonths(
750 const uno::Reference
< beans::XPropertySet
>& xOptions
,
751 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
752 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
754 sal_Int32 nNullDate
= GetNullDate( xOptions
);
756 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
757 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
759 sal_uInt16 nDay1
,nMonth1
,nYear1
;
760 sal_uInt16 nDay2
,nMonth2
,nYear2
;
761 DaysToDate(nDays1
,nDay1
,nMonth1
,nYear1
);
762 DaysToDate(nDays2
,nDay2
,nMonth2
,nYear2
);
764 sal_Int32 nRet
= nMonth2
- nMonth1
+ (nYear2
- nYear1
) * 12;
765 if ( nMode
== 1 || nDays1
== nDays2
) return nRet
;
767 if ( nDays1
< nDays2
)
786 * Get Year difference between 2 dates
788 * two modes are provided
790 * mode 0 is the interval between the dates in years
792 * mode 1 is the difference in calendar years
795 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffYears(
796 const uno::Reference
< beans::XPropertySet
>& xOptions
,
797 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
798 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
801 return getDiffMonths( xOptions
, nStartDate
, nEndDate
, nMode
) / 12;
803 sal_Int32 nNullDate
= GetNullDate( xOptions
);
805 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
806 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
808 sal_uInt16 nDay1
,nMonth1
,nYear1
;
809 sal_uInt16 nDay2
,nMonth2
,nYear2
;
810 DaysToDate(nDays1
,nDay1
,nMonth1
,nYear1
);
811 DaysToDate(nDays2
,nDay2
,nMonth2
,nYear2
);
813 return nYear2
- nYear1
;
817 * Check if a Date is in a leap year in the Gregorian calendar
820 sal_Int32 SAL_CALL
ScaDateAddIn::getIsLeapYear(
821 const uno::Reference
< beans::XPropertySet
>& xOptions
,
822 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
824 sal_Int32 nNullDate
= GetNullDate( xOptions
);
825 sal_Int32 nDays
= nDate
+ nNullDate
;
827 sal_uInt16 nDay
, nMonth
, nYear
;
828 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
830 return (sal_Int32
)IsLeapYear(nYear
);
834 * Get the Number of Days in the month for a date
837 sal_Int32 SAL_CALL
ScaDateAddIn::getDaysInMonth(
838 const uno::Reference
<beans::XPropertySet
>& xOptions
,
839 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
841 sal_Int32 nNullDate
= GetNullDate( xOptions
);
842 sal_Int32 nDays
= nDate
+ nNullDate
;
844 sal_uInt16 nDay
, nMonth
, nYear
;
845 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
847 return DaysInMonth( nMonth
, nYear
);
851 * Get number of days in the year of a date specified
854 sal_Int32 SAL_CALL
ScaDateAddIn::getDaysInYear(
855 const uno::Reference
< beans::XPropertySet
>& xOptions
,
856 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
858 sal_Int32 nNullDate
= GetNullDate( xOptions
);
859 sal_Int32 nDays
= nDate
+ nNullDate
;
861 sal_uInt16 nDay
, nMonth
, nYear
;
862 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
864 return ( IsLeapYear(nYear
) ? 366 : 365 );
868 * Get number of weeks in the year for a date
870 * Most years have 52 weeks, but years that start on a Thursday
871 * and leep years that start on a Wednesday have 53 weeks
873 * The International Standard IS-8601 has decreed that Monday
874 * shall be the first day of the week.
876 * A WeekDay can be calculated by substracting 1 and calculating the rest of
877 * a division by 7 from the internal date represention
878 * which gives a 0 - 6 value for Monday - Sunday
880 * @see #IsLeapYear #WeekNumber
883 sal_Int32 SAL_CALL
ScaDateAddIn::getWeeksInYear(
884 const uno::Reference
< beans::XPropertySet
>& xOptions
,
885 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
887 sal_Int32 nNullDate
= GetNullDate( xOptions
);
888 sal_Int32 nDays
= nDate
+ nNullDate
;
890 sal_uInt16 nDay
, nMonth
, nYear
;
891 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
893 sal_Int32 nJan1WeekDay
= ( DateToDays(1,1,nYear
) - 1) % 7;
896 if ( nJan1WeekDay
== 3 ) /* Thursday */
898 else if ( nJan1WeekDay
== 2 ) /* Wednesday */
899 nRet
= ( IsLeapYear(nYear
) ? 53 : 52 );
907 * Encrypt or decrypt a string using ROT13 algorithm
909 * This function rotates each character by 13 in the alphabet.
910 * Only the characters 'a' ... 'z' and 'A' ... 'Z' are modified.
913 OUString SAL_CALL
ScaDateAddIn::getRot13( const OUString
& aSrcString
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
915 OUStringBuffer
aBuffer( aSrcString
);
916 for( sal_Int32 nIndex
= 0; nIndex
< aBuffer
.getLength(); nIndex
++ )
918 sal_Unicode cChar
= aBuffer
[nIndex
];
919 if( ((cChar
>= 'a') && (cChar
<= 'z') && ((cChar
+= 13) > 'z')) ||
920 ((cChar
>= 'A') && (cChar
<= 'Z') && ((cChar
+= 13) > 'Z')) )
922 aBuffer
[nIndex
] = cChar
;
924 return aBuffer
.makeStringAndClear();
927 //------------------------------------------------------------------
929 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */