1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 //------------------------------------------------------------------
31 // date functions add in
33 //------------------------------------------------------------------
35 #include "datefunc.hxx"
36 #include "datefunc.hrc"
37 #include <cppuhelper/factory.hxx>
38 #include <osl/diagnose.h>
39 #include <rtl/ustrbuf.hxx>
40 #include <tools/resmgr.hxx>
41 #include <tools/rcid.h>
42 #include <com/sun/star/util/Date.hpp>
44 using namespace ::com::sun::star
;
45 using namespace ::rtl
;
47 //------------------------------------------------------------------
49 #define ADDIN_SERVICE "com.sun.star.sheet.AddIn"
50 #define MY_SERVICE "com.sun.star.sheet.addin.DateFunctions"
51 #define MY_IMPLNAME "com.sun.star.sheet.addin.DateFunctionsImpl"
53 //------------------------------------------------------------------
55 #define STR_FROM_ANSI( s ) OUString( s, strlen( s ), RTL_TEXTENCODING_MS_1252 )
57 //------------------------------------------------------------------
59 const sal_uInt32
ScaList::nStartSize
= 16;
60 const sal_uInt32
ScaList::nIncrSize
= 16;
63 pData( new void*[ nStartSize
] ),
79 void** pNewData
= new void*[ nSize
];
80 memcpy( pNewData
, pData
, nCount
* sizeof( void* ) );
86 //------------------------------------------------------------------
88 ScaStringList::~ScaStringList()
90 for( OUString
* pStr
= First(); pStr
; pStr
= Next() )
94 //------------------------------------------------------------------
96 ScaResId::ScaResId( sal_uInt16 nId
, ResMgr
& rResMgr
) :
102 //------------------------------------------------------------------
104 #define UNIQUE sal_False // function name does not exist in Calc
105 #define DOUBLE sal_True // function name exists in Calc
107 #define STDPAR sal_False // all parameters are described
108 #define INTPAR sal_True // first parameter is internal
110 #define FUNCDATA( FuncName, ParamCount, Category, Double, IntPar ) \
111 { "get" #FuncName, DATE_FUNCNAME_##FuncName, DATE_FUNCDESC_##FuncName, DATE_DEFFUNCNAME_##FuncName, ParamCount, Category, Double, IntPar }
113 const ScaFuncDataBase pFuncDataArr
[] =
115 FUNCDATA( DiffWeeks
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
116 FUNCDATA( DiffMonths
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
117 FUNCDATA( DiffYears
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
118 FUNCDATA( IsLeapYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
119 FUNCDATA( DaysInMonth
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
120 FUNCDATA( DaysInYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
121 FUNCDATA( WeeksInYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
122 FUNCDATA( Rot13
, 1, ScaCat_Text
, UNIQUE
, STDPAR
)
128 //------------------------------------------------------------------
130 ScaFuncData::ScaFuncData( const ScaFuncDataBase
& rBaseData
, ResMgr
& rResMgr
) :
131 aIntName( OUString::createFromAscii( rBaseData
.pIntName
) ),
132 nUINameID( rBaseData
.nUINameID
),
133 nDescrID( rBaseData
.nDescrID
),
134 nCompListID( rBaseData
.nCompListID
),
135 nParamCount( rBaseData
.nParamCount
),
136 eCat( rBaseData
.eCat
),
137 bDouble( rBaseData
.bDouble
),
138 bWithOpt( rBaseData
.bWithOpt
)
140 ScaResStringArrLoader
aArrLoader( RID_DATE_DEFFUNCTION_NAMES
, nCompListID
, rResMgr
);
141 const ResStringArray
& rArr
= aArrLoader
.GetStringArray();
143 for( sal_uInt16 nIndex
= 0; nIndex
< rArr
.Count(); nIndex
++ )
144 aCompList
.Append( rArr
.GetString( nIndex
) );
147 ScaFuncData::~ScaFuncData()
151 sal_uInt16
ScaFuncData::GetStrIndex( sal_uInt16 nParam
) const
155 return (nParam
> nParamCount
) ? (nParamCount
* 2) : (nParam
* 2);
159 //------------------------------------------------------------------
161 ScaFuncDataList::ScaFuncDataList( ResMgr
& rResMgr
) :
164 for( sal_uInt16 nIndex
= 0; nIndex
< SAL_N_ELEMENTS(pFuncDataArr
); nIndex
++ )
165 Append( new ScaFuncData( pFuncDataArr
[ nIndex
], rResMgr
) );
168 ScaFuncDataList::~ScaFuncDataList()
170 for( ScaFuncData
* pFData
= First(); pFData
; pFData
= Next() )
174 const ScaFuncData
* ScaFuncDataList::Get( const OUString
& rProgrammaticName
) const
176 if( aLastName
== rProgrammaticName
)
179 for( sal_uInt32 nIndex
= 0; nIndex
< Count(); nIndex
++ )
181 const ScaFuncData
* pCurr
= Get( nIndex
);
182 if( pCurr
->Is( rProgrammaticName
) )
184 const_cast< ScaFuncDataList
* >( this )->aLastName
= rProgrammaticName
;
185 const_cast< ScaFuncDataList
* >( this )->nLast
= nIndex
;
193 //------------------------------------------------------------------
195 ScaFuncRes::ScaFuncRes( ResId
& rResId
, ResMgr
& rResMgr
, sal_uInt16 nIndex
, OUString
& rRet
) :
198 rRet
= String( ScaResId( nIndex
, rResMgr
) );
203 //------------------------------------------------------------------
205 // entry points for service registration / instantiation
207 //------------------------------------------------------------------
209 uno::Reference
< uno::XInterface
> SAL_CALL
ScaDateAddIn_CreateInstance(
210 const uno::Reference
< lang::XMultiServiceFactory
>& )
212 static uno::Reference
< uno::XInterface
> xInst
= (cppu::OWeakObject
*) new ScaDateAddIn();
217 //------------------------------------------------------------------------
221 SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
date_component_getFactory(
222 const sal_Char
* pImplName
, void * pServiceManager
, void * /*pRegistryKey*/ )
226 if ( pServiceManager
&&
227 OUString::createFromAscii( pImplName
) == ScaDateAddIn::getImplementationName_Static() )
229 uno::Reference
< lang::XSingleServiceFactory
> xFactory( cppu::createOneInstanceFactory(
230 reinterpret_cast< lang::XMultiServiceFactory
* >( pServiceManager
),
231 ScaDateAddIn::getImplementationName_Static(),
232 ScaDateAddIn_CreateInstance
,
233 ScaDateAddIn::getSupportedServiceNames_Static() ) );
238 pRet
= xFactory
.get();
247 //------------------------------------------------------------------------
249 // "normal" service implementation
251 //------------------------------------------------------------------------
253 ScaDateAddIn::ScaDateAddIn() :
256 pFuncDataList( NULL
)
260 ScaDateAddIn::~ScaDateAddIn()
263 delete pFuncDataList
;
265 delete[] pDefLocales
;
267 // pResMgr already deleted (_all_ resource managers are deleted _before_ this dtor is called)
270 static const sal_Char
* pLang
[] = { "de", "en" };
271 static const sal_Char
* pCoun
[] = { "DE", "US" };
272 static const sal_uInt32 nNumOfLoc
= SAL_N_ELEMENTS( pLang
);
274 void ScaDateAddIn::InitDefLocales()
276 pDefLocales
= new lang::Locale
[ nNumOfLoc
];
278 for( sal_uInt32 nIndex
= 0; nIndex
< nNumOfLoc
; nIndex
++ )
280 pDefLocales
[ nIndex
].Language
= OUString::createFromAscii( pLang
[ nIndex
] );
281 pDefLocales
[ nIndex
].Country
= OUString::createFromAscii( pCoun
[ nIndex
] );
285 const lang::Locale
& ScaDateAddIn::GetLocale( sal_uInt32 nIndex
)
290 return (nIndex
< sizeof( pLang
)) ? pDefLocales
[ nIndex
] : aFuncLoc
;
293 ResMgr
& ScaDateAddIn::GetResMgr() throw( uno::RuntimeException
)
297 InitData(); // try to get resource manager
299 throw uno::RuntimeException();
304 void ScaDateAddIn::InitData()
309 OString
aModName( "date" );
310 pResMgr
= ResMgr::CreateResMgr( aModName
.getStr(), aFuncLoc
);
313 delete pFuncDataList
;
315 pFuncDataList
= pResMgr
? new ScaFuncDataList( *pResMgr
) : NULL
;
324 OUString
ScaDateAddIn::GetDisplFuncStr( sal_uInt16 nResId
) throw( uno::RuntimeException
)
326 return ScaResStringLoader( RID_DATE_FUNCTION_NAMES
, nResId
, GetResMgr() ).GetString();
329 OUString
ScaDateAddIn::GetFuncDescrStr( sal_uInt16 nResId
, sal_uInt16 nStrIndex
) throw( uno::RuntimeException
)
333 ScaResPublisher
aResPubl( ScaResId( RID_DATE_FUNCTION_DESCRIPTIONS
, GetResMgr() ) );
334 ScaResId
aResId( nResId
, GetResMgr() );
335 aResId
.SetRT( RSC_RESOURCE
);
337 if( aResPubl
.IsAvailableRes( aResId
) )
338 ScaFuncRes
aSubRes( aResId
, GetResMgr(), nStrIndex
, aRet
);
340 aResPubl
.FreeResource();
345 //------------------------------------------------------------------------
347 OUString
ScaDateAddIn::getImplementationName_Static()
349 return OUString(RTL_CONSTASCII_USTRINGPARAM( MY_IMPLNAME
));
352 uno::Sequence
< OUString
> ScaDateAddIn::getSupportedServiceNames_Static()
354 uno::Sequence
< OUString
> aRet( 2 );
355 OUString
* pArray
= aRet
.getArray();
356 pArray
[0] = OUString(RTL_CONSTASCII_USTRINGPARAM( ADDIN_SERVICE
));
357 pArray
[1] = OUString(RTL_CONSTASCII_USTRINGPARAM( MY_SERVICE
));
363 OUString SAL_CALL
ScaDateAddIn::getServiceName() throw( uno::RuntimeException
)
365 // name of specific AddIn service
366 return OUString(RTL_CONSTASCII_USTRINGPARAM( MY_SERVICE
));
371 OUString SAL_CALL
ScaDateAddIn::getImplementationName() throw( uno::RuntimeException
)
373 return getImplementationName_Static();
376 sal_Bool SAL_CALL
ScaDateAddIn::supportsService( const OUString
& aServiceName
) throw( uno::RuntimeException
)
378 return aServiceName
== ADDIN_SERVICE
|| aServiceName
== MY_SERVICE
;
381 uno::Sequence
< OUString
> SAL_CALL
ScaDateAddIn::getSupportedServiceNames() throw( uno::RuntimeException
)
383 return getSupportedServiceNames_Static();
388 void SAL_CALL
ScaDateAddIn::setLocale( const lang::Locale
& eLocale
) throw( uno::RuntimeException
)
391 InitData(); // change of locale invalidates resources!
394 lang::Locale SAL_CALL
ScaDateAddIn::getLocale() throw( uno::RuntimeException
)
399 //------------------------------------------------------------------
401 // function descriptions start here
403 //------------------------------------------------------------------
407 OUString SAL_CALL
ScaDateAddIn::getProgrammaticFuntionName( const OUString
& ) throw( uno::RuntimeException
)
410 // (but should be implemented for other uses of the AddIn service)
414 OUString SAL_CALL
ScaDateAddIn::getDisplayFunctionName( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
418 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
421 aRet
= GetDisplFuncStr( pFData
->GetUINameID() );
422 if( pFData
->IsDouble() )
423 aRet
+= STR_FROM_ANSI( "_ADD" );
427 aRet
= STR_FROM_ANSI( "UNKNOWNFUNC_" );
428 aRet
+= aProgrammaticName
;
434 OUString SAL_CALL
ScaDateAddIn::getFunctionDescription( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
438 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
440 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), 1 );
445 OUString SAL_CALL
ScaDateAddIn::getDisplayArgumentName(
446 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
)
450 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
451 if( pFData
&& (nArgument
<= 0xFFFF) )
453 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
455 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
);
457 aRet
= STR_FROM_ANSI( "internal" );
463 OUString SAL_CALL
ScaDateAddIn::getArgumentDescription(
464 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
)
468 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
469 if( pFData
&& (nArgument
<= 0xFFFF) )
471 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
473 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
+ 1 );
475 aRet
= STR_FROM_ANSI( "for internal use only" );
481 OUString SAL_CALL
ScaDateAddIn::getProgrammaticCategoryName(
482 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
486 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
489 switch( pFData
->GetCategory() )
491 case ScaCat_DateTime
: aRet
= STR_FROM_ANSI( "Date&Time" ); break;
492 case ScaCat_Text
: aRet
= STR_FROM_ANSI( "Text" ); break;
493 case ScaCat_Finance
: aRet
= STR_FROM_ANSI( "Financial" ); break;
494 case ScaCat_Inf
: aRet
= STR_FROM_ANSI( "Information" ); break;
495 case ScaCat_Math
: aRet
= STR_FROM_ANSI( "Mathematical" ); break;
496 case ScaCat_Tech
: aRet
= STR_FROM_ANSI( "Technical" ); break;
497 default: // to prevent compiler warnings
503 aRet
= STR_FROM_ANSI( "Add-In" );
507 OUString SAL_CALL
ScaDateAddIn::getDisplayCategoryName(
508 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
510 return getProgrammaticCategoryName( aProgrammaticName
);
514 // XCompatibilityNames
516 uno::Sequence
< sheet::LocalizedName
> SAL_CALL
ScaDateAddIn::getCompatibilityNames(
517 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
519 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
521 return uno::Sequence
< sheet::LocalizedName
>( 0 );
523 const ScaStringList
& rStrList
= pFData
->GetCompNameList();
524 sal_uInt32 nCount
= rStrList
.Count();
526 uno::Sequence
< sheet::LocalizedName
> aRet( nCount
);
527 sheet::LocalizedName
* pArray
= aRet
.getArray();
529 for( sal_uInt32 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
530 pArray
[ nIndex
] = sheet::LocalizedName( GetLocale( nIndex
), *rStrList
.Get( nIndex
) );
536 //------------------------------------------------------------------
538 // function implementation starts here
540 //------------------------------------------------------------------
542 // auxiliary functions
544 sal_Bool
IsLeapYear( sal_uInt16 nYear
)
546 return ((((nYear
% 4) == 0) && ((nYear
% 100) != 0)) || ((nYear
% 400) == 0));
549 sal_uInt16
DaysInMonth( sal_uInt16 nMonth
, sal_uInt16 nYear
)
551 static sal_uInt16 aDaysInMonth
[12] = { 31, 28, 31, 30, 31, 30,
552 31, 31, 30, 31, 30, 31 };
555 return aDaysInMonth
[nMonth
-1];
558 if ( IsLeapYear(nYear
) )
559 return aDaysInMonth
[nMonth
-1] + 1;
561 return aDaysInMonth
[nMonth
-1];
566 * Convert a date to a count of days starting from 01/01/0001
568 * The internal representation of a Date used in this Addin
569 * is the number of days between 01/01/0001 and the date
570 * this function converts a Day , Month, Year representation
571 * to this internal Date value.
574 sal_Int32
DateToDays( sal_uInt16 nDay
, sal_uInt16 nMonth
, sal_uInt16 nYear
)
576 sal_Int32 nDays
= ((sal_Int32
)nYear
-1) * 365;
577 nDays
+= ((nYear
-1) / 4) - ((nYear
-1) / 100) + ((nYear
-1) / 400);
579 for( sal_uInt16 i
= 1; i
< nMonth
; i
++ )
580 nDays
+= DaysInMonth(i
,nYear
);
587 * Convert a count of days starting from 01/01/0001 to a date
589 * The internal representation of a Date used in this Addin
590 * is the number of days between 01/01/0001 and the date
591 * this function converts this internal Date value
592 * to a Day , Month, Year representation of a Date.
595 void DaysToDate( sal_Int32 nDays
,
596 sal_uInt16
& rDay
, sal_uInt16
& rMonth
, sal_uInt16
& rYear
)
597 throw( lang::IllegalArgumentException
)
600 throw lang::IllegalArgumentException();
609 rYear
= (sal_uInt16
)((nTempDays
/ 365) - i
);
610 nTempDays
-= ((sal_Int32
) rYear
-1) * 365;
611 nTempDays
-= (( rYear
-1) / 4) - (( rYear
-1) / 100) + ((rYear
-1) / 400);
620 if ( nTempDays
> 365 )
622 if ( (nTempDays
!= 366) || !IsLeapYear( rYear
) )
633 while ( (sal_Int32
)nTempDays
> DaysInMonth( rMonth
, rYear
) )
635 nTempDays
-= DaysInMonth( rMonth
, rYear
);
638 rDay
= (sal_uInt16
)nTempDays
;
642 * Get the null date used by the spreadsheet document
644 * The internal representation of a Date used in this Addin
645 * is the number of days between 01/01/0001 and the date
646 * this function returns this internal Date value for the document null date
650 sal_Int32
GetNullDate( const uno::Reference
< beans::XPropertySet
>& xOptions
)
651 throw( uno::RuntimeException
)
657 uno::Any aAny
= xOptions
->getPropertyValue(
658 OUString(RTL_CONSTASCII_USTRINGPARAM( "NullDate" )) );
660 if ( aAny
>>= aDate
)
661 return DateToDays( aDate
.Day
, aDate
.Month
, aDate
.Year
);
663 catch (uno::Exception
&)
668 // no null date available -> no calculations possible
669 throw uno::RuntimeException();
675 * Get week difference between 2 dates
677 * new Weeks(date1,date2,mode) function for StarCalc
679 * Two modes of operation are provided.
680 * The first is just a simple division by 7 calculation.
682 * The second calculates the diffence by week of year.
684 * The International Standard IS-8601 has decreed that Monday
685 * shall be the first day of the week.
687 * A week that lies partly in one year and partly in annother
688 * is assigned a number in the the year in which most of its days lie.
690 * That means that week 1 of any year is the week that contains the 4. January
692 * The internal representation of a Date used in the Addin is the number of days based on 01/01/0001
694 * A WeekDay can be then calculated by substracting 1 and calculating the rest of
695 * a division by 7, which gives a 0 - 6 value for Monday - Sunday
697 * Using the 4. January rule explained above the formula
699 * nWeek1= ( nDays1 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
701 * calculates a number between 0-53 for each day which is in the same year as nJan4
702 * where 0 means that this week belonged to the year before.
704 * If a day in the same or annother year is used in this formula this calculates
705 * an calendar week offset from a given 4. January
707 * nWeek2 = ( nDays2 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
709 * The 4.January of first Date Argument can thus be used to calculate
710 * the week difference by calendar weeks which is then nWeek = nWeek2 - nWeek1
712 * which can be optimized to
714 * nWeek = ( (nDays2-nJan4+((nJan4-1)%7))/7 ) - ( (nDays1-nJan4+((nJan4-1)%7))/7 )
716 * Note: All calculations are operating on the long integer data type
717 * % is the modulo operator in C which calculates the rest of an Integer division
720 * mode 0 is the interval between the dates in month, that is days / 7
722 * mode 1 is the difference by week of year
726 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffWeeks(
727 const uno::Reference
< beans::XPropertySet
>& xOptions
,
728 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
729 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
731 sal_Int32 nNullDate
= GetNullDate( xOptions
);
733 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
734 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
740 sal_uInt16 nDay
,nMonth
,nYear
;
741 DaysToDate( nDays1
, nDay
, nMonth
, nYear
);
742 sal_Int32 nJan4
= DateToDays( 4, 1, nYear
);
744 nRet
= ( (nDays2
-nJan4
+((nJan4
-1)%7))/7 ) - ( (nDays1
-nJan4
+((nJan4
-1)%7))/7 );
748 nRet
= (nDays2
- nDays1
) / 7;
754 * Get month difference between 2 dates
755 * =Month(start, end, mode) Function for StarCalc
757 * two modes are provided
759 * mode 0 is the interval between the dates in month
761 * mode 1 is the difference in calendar month
764 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffMonths(
765 const uno::Reference
< beans::XPropertySet
>& xOptions
,
766 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
767 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
769 sal_Int32 nNullDate
= GetNullDate( xOptions
);
771 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
772 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
774 sal_uInt16 nDay1
,nMonth1
,nYear1
;
775 sal_uInt16 nDay2
,nMonth2
,nYear2
;
776 DaysToDate(nDays1
,nDay1
,nMonth1
,nYear1
);
777 DaysToDate(nDays2
,nDay2
,nMonth2
,nYear2
);
779 sal_Int32 nRet
= nMonth2
- nMonth1
+ (nYear2
- nYear1
) * 12;
780 if ( nMode
== 1 || nDays1
== nDays2
) return nRet
;
782 if ( nDays1
< nDays2
)
801 * Get Year difference between 2 dates
803 * two modes are provided
805 * mode 0 is the interval between the dates in years
807 * mode 1 is the difference in calendar years
810 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffYears(
811 const uno::Reference
< beans::XPropertySet
>& xOptions
,
812 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
813 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
816 return getDiffMonths( xOptions
, nStartDate
, nEndDate
, nMode
) / 12;
818 sal_Int32 nNullDate
= GetNullDate( xOptions
);
820 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
821 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
823 sal_uInt16 nDay1
,nMonth1
,nYear1
;
824 sal_uInt16 nDay2
,nMonth2
,nYear2
;
825 DaysToDate(nDays1
,nDay1
,nMonth1
,nYear1
);
826 DaysToDate(nDays2
,nDay2
,nMonth2
,nYear2
);
828 return nYear2
- nYear1
;
832 * Check if a Date is in a leap year in the Gregorian calendar
835 sal_Int32 SAL_CALL
ScaDateAddIn::getIsLeapYear(
836 const uno::Reference
< beans::XPropertySet
>& xOptions
,
837 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
839 sal_Int32 nNullDate
= GetNullDate( xOptions
);
840 sal_Int32 nDays
= nDate
+ nNullDate
;
842 sal_uInt16 nDay
, nMonth
, nYear
;
843 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
845 return (sal_Int32
)IsLeapYear(nYear
);
849 * Get the Number of Days in the month for a date
852 sal_Int32 SAL_CALL
ScaDateAddIn::getDaysInMonth(
853 const uno::Reference
<beans::XPropertySet
>& xOptions
,
854 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
856 sal_Int32 nNullDate
= GetNullDate( xOptions
);
857 sal_Int32 nDays
= nDate
+ nNullDate
;
859 sal_uInt16 nDay
, nMonth
, nYear
;
860 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
862 return DaysInMonth( nMonth
, nYear
);
866 * Get number of days in the year of a date specified
869 sal_Int32 SAL_CALL
ScaDateAddIn::getDaysInYear(
870 const uno::Reference
< beans::XPropertySet
>& xOptions
,
871 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
873 sal_Int32 nNullDate
= GetNullDate( xOptions
);
874 sal_Int32 nDays
= nDate
+ nNullDate
;
876 sal_uInt16 nDay
, nMonth
, nYear
;
877 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
879 return ( IsLeapYear(nYear
) ? 366 : 365 );
883 * Get number of weeks in the year for a date
885 * Most years have 52 weeks, but years that start on a Thursday
886 * and leep years that start on a Wednesday have 53 weeks
888 * The International Standard IS-8601 has decreed that Monday
889 * shall be the first day of the week.
891 * A WeekDay can be calculated by substracting 1 and calculating the rest of
892 * a division by 7 from the internal date represention
893 * which gives a 0 - 6 value for Monday - Sunday
895 * @see #IsLeapYear #WeekNumber
898 sal_Int32 SAL_CALL
ScaDateAddIn::getWeeksInYear(
899 const uno::Reference
< beans::XPropertySet
>& xOptions
,
900 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
902 sal_Int32 nNullDate
= GetNullDate( xOptions
);
903 sal_Int32 nDays
= nDate
+ nNullDate
;
905 sal_uInt16 nDay
, nMonth
, nYear
;
906 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
908 sal_Int32 nJan1WeekDay
= ( DateToDays(1,1,nYear
) - 1) % 7;
911 if ( nJan1WeekDay
== 3 ) /* Thursday */
913 else if ( nJan1WeekDay
== 2 ) /* Wednesday */
914 nRet
= ( IsLeapYear(nYear
) ? 53 : 52 );
922 * Encrypt or decrypt a string using ROT13 algorithm
924 * This function rotates each character by 13 in the alphabet.
925 * Only the characters 'a' ... 'z' and 'A' ... 'Z' are modified.
928 OUString SAL_CALL
ScaDateAddIn::getRot13( const OUString
& aSrcString
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
930 OUStringBuffer
aBuffer( aSrcString
);
931 for( sal_Int32 nIndex
= 0; nIndex
< aBuffer
.getLength(); nIndex
++ )
933 sal_Unicode cChar
= aBuffer
[nIndex
];
934 if( ((cChar
>= 'a') && (cChar
<= 'z') && ((cChar
+= 13) > 'z')) ||
935 ((cChar
>= 'A') && (cChar
<= 'Z') && ((cChar
+= 13) > 'Z')) )
937 aBuffer
[nIndex
] = cChar
;
939 return aBuffer
.makeStringAndClear();
942 //------------------------------------------------------------------
944 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */