1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: datefunc.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 //------------------------------------------------------------------
33 // date functions add in
35 //------------------------------------------------------------------
37 #include "datefunc.hxx"
38 #ifndef _SCA_DATEFUNC_HRC
39 #include "datefunc.hrc"
41 #include <cppuhelper/factory.hxx>
42 #include <osl/diagnose.h>
43 #include <rtl/ustrbuf.hxx>
44 #include <tools/resmgr.hxx>
45 #include <tools/rcid.h>
46 #include <com/sun/star/util/Date.hpp>
48 using namespace ::com::sun::star
;
49 using namespace ::rtl
;
51 //------------------------------------------------------------------
53 #define ADDIN_SERVICE "com.sun.star.sheet.AddIn"
54 #define MY_SERVICE "com.sun.star.sheet.addin.DateFunctions"
55 #define MY_IMPLNAME "com.sun.star.sheet.addin.DateFunctionsImpl"
57 //------------------------------------------------------------------
59 #define STR_FROM_ANSI( s ) OUString( s, strlen( s ), RTL_TEXTENCODING_MS_1252 )
61 //------------------------------------------------------------------
63 const sal_uInt32
ScaList::nStartSize
= 16;
64 const sal_uInt32
ScaList::nIncrSize
= 16;
67 pData( new void*[ nStartSize
] ),
83 void** pNewData
= new void*[ nSize
];
84 memcpy( pNewData
, pData
, nCount
* sizeof( void* ) );
90 void ScaList::Insert( void* pNew
, sal_uInt32 nIndex
)
92 if( nIndex
>= nCount
)
98 void** pIns
= pData
+ nIndex
;
99 memmove( pIns
+ 1, pIns
, (nCount
- nIndex
) * sizeof( void* ) );
107 //------------------------------------------------------------------
109 ScaStringList::~ScaStringList()
111 for( OUString
* pStr
= First(); pStr
; pStr
= Next() )
115 //------------------------------------------------------------------
117 ScaResId::ScaResId( sal_uInt16 nId
, ResMgr
& rResMgr
) :
118 ResId( nId
, rResMgr
)
123 //------------------------------------------------------------------
125 #define UNIQUE sal_False // function name does not exist in Calc
126 #define DOUBLE sal_True // function name exists in Calc
128 #define STDPAR sal_False // all parameters are described
129 #define INTPAR sal_True // first parameter is internal
131 #define FUNCDATA( FuncName, ParamCount, Category, Double, IntPar ) \
132 { "get" #FuncName, DATE_FUNCNAME_##FuncName, DATE_FUNCDESC_##FuncName, DATE_DEFFUNCNAME_##FuncName, ParamCount, Category, Double, IntPar }
134 const ScaFuncDataBase pFuncDataArr
[] =
136 FUNCDATA( DiffWeeks
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
137 FUNCDATA( DiffMonths
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
138 FUNCDATA( DiffYears
, 3, ScaCat_DateTime
, UNIQUE
, INTPAR
),
139 FUNCDATA( IsLeapYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
140 FUNCDATA( DaysInMonth
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
141 FUNCDATA( DaysInYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
142 FUNCDATA( WeeksInYear
, 1, ScaCat_DateTime
, UNIQUE
, INTPAR
),
143 FUNCDATA( Rot13
, 1, ScaCat_Text
, UNIQUE
, STDPAR
)
149 //------------------------------------------------------------------
151 ScaFuncData::ScaFuncData( const ScaFuncDataBase
& rBaseData
, ResMgr
& rResMgr
) :
152 aIntName( OUString::createFromAscii( rBaseData
.pIntName
) ),
153 nUINameID( rBaseData
.nUINameID
),
154 nDescrID( rBaseData
.nDescrID
),
155 nCompListID( rBaseData
.nCompListID
),
156 nParamCount( rBaseData
.nParamCount
),
157 eCat( rBaseData
.eCat
),
158 bDouble( rBaseData
.bDouble
),
159 bWithOpt( rBaseData
.bWithOpt
)
161 ScaResStringArrLoader
aArrLoader( RID_DATE_DEFFUNCTION_NAMES
, nCompListID
, rResMgr
);
162 const ResStringArray
& rArr
= aArrLoader
.GetStringArray();
164 for( sal_uInt16 nIndex
= 0; nIndex
< rArr
.Count(); nIndex
++ )
165 aCompList
.Append( rArr
.GetString( nIndex
) );
168 ScaFuncData::~ScaFuncData()
172 sal_uInt16
ScaFuncData::GetStrIndex( sal_uInt16 nParam
) const
176 return (nParam
> nParamCount
) ? (nParamCount
* 2) : (nParam
* 2);
180 //------------------------------------------------------------------
182 ScaFuncDataList::ScaFuncDataList( ResMgr
& rResMgr
) :
185 const sal_uInt32 nCnt
= sizeof( pFuncDataArr
) / sizeof( ScaFuncDataBase
);
187 for( sal_uInt16 nIndex
= 0; nIndex
< nCnt
; nIndex
++ )
188 Append( new ScaFuncData( pFuncDataArr
[ nIndex
], rResMgr
) );
191 ScaFuncDataList::~ScaFuncDataList()
193 for( ScaFuncData
* pFData
= First(); pFData
; pFData
= Next() )
197 const ScaFuncData
* ScaFuncDataList::Get( const OUString
& rProgrammaticName
) const
199 if( aLastName
== rProgrammaticName
)
202 for( sal_uInt32 nIndex
= 0; nIndex
< Count(); nIndex
++ )
204 const ScaFuncData
* pCurr
= Get( nIndex
);
205 if( pCurr
->Is( rProgrammaticName
) )
207 const_cast< ScaFuncDataList
* >( this )->aLastName
= rProgrammaticName
;
208 const_cast< ScaFuncDataList
* >( this )->nLast
= nIndex
;
216 //------------------------------------------------------------------
218 ScaFuncRes::ScaFuncRes( ResId
& rResId
, ResMgr
& rResMgr
, sal_uInt16 nIndex
, OUString
& rRet
) :
221 rRet
= String( ScaResId( nIndex
, rResMgr
) );
226 //------------------------------------------------------------------
228 // entry points for service registration / instantiation
230 //------------------------------------------------------------------
232 uno::Reference
< uno::XInterface
> SAL_CALL
ScaDateAddIn_CreateInstance(
233 const uno::Reference
< lang::XMultiServiceFactory
>& )
235 static uno::Reference
< uno::XInterface
> xInst
= (cppu::OWeakObject
*) new ScaDateAddIn();
240 //------------------------------------------------------------------------
244 void SAL_CALL
component_getImplementationEnvironment(
245 const sal_Char
** ppEnvTypeName
, uno_Environment
** /*ppEnv*/ )
247 *ppEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
250 sal_Bool SAL_CALL
component_writeInfo(
251 void * /*pServiceManager*/, registry::XRegistryKey
* pRegistryKey
)
257 OUString aImpl
= OUString::createFromAscii( "/" );
258 aImpl
+= ScaDateAddIn::getImplementationName_Static();
259 aImpl
+= OUString::createFromAscii( "/UNO/SERVICES" );
261 uno::Reference
< registry::XRegistryKey
> xNewKey(
262 reinterpret_cast< registry::XRegistryKey
* >( pRegistryKey
)->createKey( aImpl
) );
264 uno::Sequence
< OUString
> aSequ
= ScaDateAddIn::getSupportedServiceNames_Static();
265 const OUString
* pArray
= aSequ
.getConstArray();
266 for( sal_Int32 i
= 0; i
< aSequ
.getLength(); i
++ )
267 xNewKey
->createKey( pArray
[i
] );
271 catch (registry::InvalidRegistryException
&)
273 OSL_ENSURE( sal_False
, "### InvalidRegistryException!" );
279 void * SAL_CALL
component_getFactory(
280 const sal_Char
* pImplName
, void * pServiceManager
, void * /*pRegistryKey*/ )
284 if ( pServiceManager
&&
285 OUString::createFromAscii( pImplName
) == ScaDateAddIn::getImplementationName_Static() )
287 uno::Reference
< lang::XSingleServiceFactory
> xFactory( cppu::createOneInstanceFactory(
288 reinterpret_cast< lang::XMultiServiceFactory
* >( pServiceManager
),
289 ScaDateAddIn::getImplementationName_Static(),
290 ScaDateAddIn_CreateInstance
,
291 ScaDateAddIn::getSupportedServiceNames_Static() ) );
296 pRet
= xFactory
.get();
305 //------------------------------------------------------------------------
307 // "normal" service implementation
309 //------------------------------------------------------------------------
311 ScaDateAddIn::ScaDateAddIn() :
314 pFuncDataList( NULL
)
318 ScaDateAddIn::~ScaDateAddIn()
321 delete pFuncDataList
;
323 delete[] pDefLocales
;
325 // pResMgr already deleted (_all_ resource managers are deleted _before_ this dtor is called)
328 static const sal_Char
* pLang
[] = { "de", "en" };
329 static const sal_Char
* pCoun
[] = { "DE", "US" };
330 static const sal_uInt32 nNumOfLoc
= sizeof( pLang
) / sizeof( sal_Char
* );
332 void ScaDateAddIn::InitDefLocales()
334 pDefLocales
= new lang::Locale
[ nNumOfLoc
];
336 for( sal_uInt32 nIndex
= 0; nIndex
< nNumOfLoc
; nIndex
++ )
338 pDefLocales
[ nIndex
].Language
= OUString::createFromAscii( pLang
[ nIndex
] );
339 pDefLocales
[ nIndex
].Country
= OUString::createFromAscii( pCoun
[ nIndex
] );
343 const lang::Locale
& ScaDateAddIn::GetLocale( sal_uInt32 nIndex
)
348 return (nIndex
< sizeof( pLang
)) ? pDefLocales
[ nIndex
] : aFuncLoc
;
351 ResMgr
& ScaDateAddIn::GetResMgr() throw( uno::RuntimeException
)
355 InitData(); // try to get resource manager
357 throw uno::RuntimeException();
362 void ScaDateAddIn::InitData()
367 OString
aModName( "date" );
368 pResMgr
= ResMgr::CreateResMgr( (const sal_Char
*) aModName
,
372 delete pFuncDataList
;
374 pFuncDataList
= pResMgr
? new ScaFuncDataList( *pResMgr
) : NULL
;
383 OUString
ScaDateAddIn::GetDisplFuncStr( sal_uInt16 nResId
) throw( uno::RuntimeException
)
385 return ScaResStringLoader( RID_DATE_FUNCTION_NAMES
, nResId
, GetResMgr() ).GetString();
388 OUString
ScaDateAddIn::GetFuncDescrStr( sal_uInt16 nResId
, sal_uInt16 nStrIndex
) throw( uno::RuntimeException
)
392 ScaResPublisher
aResPubl( ScaResId( RID_DATE_FUNCTION_DESCRIPTIONS
, GetResMgr() ) );
393 ScaResId
aResId( nResId
, GetResMgr() );
394 aResId
.SetRT( RSC_RESOURCE
);
396 if( aResPubl
.IsAvailableRes( aResId
) )
397 ScaFuncRes
aSubRes( aResId
, GetResMgr(), nStrIndex
, aRet
);
399 aResPubl
.FreeResource();
404 //------------------------------------------------------------------------
406 OUString
ScaDateAddIn::getImplementationName_Static()
408 return OUString::createFromAscii( MY_IMPLNAME
);
411 uno::Sequence
< OUString
> ScaDateAddIn::getSupportedServiceNames_Static()
413 uno::Sequence
< OUString
> aRet( 2 );
414 OUString
* pArray
= aRet
.getArray();
415 pArray
[0] = OUString::createFromAscii( ADDIN_SERVICE
);
416 pArray
[1] = OUString::createFromAscii( MY_SERVICE
);
422 OUString SAL_CALL
ScaDateAddIn::getServiceName() throw( uno::RuntimeException
)
424 // name of specific AddIn service
425 return OUString::createFromAscii( MY_SERVICE
);
430 OUString SAL_CALL
ScaDateAddIn::getImplementationName() throw( uno::RuntimeException
)
432 return getImplementationName_Static();
435 sal_Bool SAL_CALL
ScaDateAddIn::supportsService( const OUString
& aServiceName
) throw( uno::RuntimeException
)
437 return aServiceName
.equalsAscii( ADDIN_SERVICE
) ||
438 aServiceName
.equalsAscii( MY_SERVICE
);
441 uno::Sequence
< OUString
> SAL_CALL
ScaDateAddIn::getSupportedServiceNames() throw( uno::RuntimeException
)
443 return getSupportedServiceNames_Static();
448 void SAL_CALL
ScaDateAddIn::setLocale( const lang::Locale
& eLocale
) throw( uno::RuntimeException
)
451 InitData(); // change of locale invalidates resources!
454 lang::Locale SAL_CALL
ScaDateAddIn::getLocale() throw( uno::RuntimeException
)
459 //------------------------------------------------------------------
461 // function descriptions start here
463 //------------------------------------------------------------------
467 OUString SAL_CALL
ScaDateAddIn::getProgrammaticFuntionName( const OUString
& ) throw( uno::RuntimeException
)
470 // (but should be implemented for other uses of the AddIn service)
474 OUString SAL_CALL
ScaDateAddIn::getDisplayFunctionName( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
478 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
481 aRet
= GetDisplFuncStr( pFData
->GetUINameID() );
482 if( pFData
->IsDouble() )
483 aRet
+= STR_FROM_ANSI( "_ADD" );
487 aRet
= STR_FROM_ANSI( "UNKNOWNFUNC_" );
488 aRet
+= aProgrammaticName
;
494 OUString SAL_CALL
ScaDateAddIn::getFunctionDescription( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
498 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
500 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), 1 );
505 OUString SAL_CALL
ScaDateAddIn::getDisplayArgumentName(
506 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
)
510 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
511 if( pFData
&& (nArgument
<= 0xFFFF) )
513 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
515 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
);
517 aRet
= STR_FROM_ANSI( "internal" );
523 OUString SAL_CALL
ScaDateAddIn::getArgumentDescription(
524 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
)
528 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
529 if( pFData
&& (nArgument
<= 0xFFFF) )
531 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
533 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
+ 1 );
535 aRet
= STR_FROM_ANSI( "for internal use only" );
541 OUString SAL_CALL
ScaDateAddIn::getProgrammaticCategoryName(
542 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
546 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
549 switch( pFData
->GetCategory() )
551 case ScaCat_DateTime
: aRet
= STR_FROM_ANSI( "Date&Time" ); break;
552 case ScaCat_Text
: aRet
= STR_FROM_ANSI( "Text" ); break;
553 case ScaCat_Finance
: aRet
= STR_FROM_ANSI( "Financial" ); break;
554 case ScaCat_Inf
: aRet
= STR_FROM_ANSI( "Information" ); break;
555 case ScaCat_Math
: aRet
= STR_FROM_ANSI( "Mathematical" ); break;
556 case ScaCat_Tech
: aRet
= STR_FROM_ANSI( "Technical" ); break;
557 default: // to prevent compiler warnings
562 if( !aRet
.getLength() )
563 aRet
= STR_FROM_ANSI( "Add-In" );
567 OUString SAL_CALL
ScaDateAddIn::getDisplayCategoryName(
568 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
570 return getProgrammaticCategoryName( aProgrammaticName
);
574 // XCompatibilityNames
576 uno::Sequence
< sheet::LocalizedName
> SAL_CALL
ScaDateAddIn::getCompatibilityNames(
577 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
)
579 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
581 return uno::Sequence
< sheet::LocalizedName
>( 0 );
583 const ScaStringList
& rStrList
= pFData
->GetCompNameList();
584 sal_uInt32 nCount
= rStrList
.Count();
586 uno::Sequence
< sheet::LocalizedName
> aRet( nCount
);
587 sheet::LocalizedName
* pArray
= aRet
.getArray();
589 for( sal_uInt32 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
590 pArray
[ nIndex
] = sheet::LocalizedName( GetLocale( nIndex
), *rStrList
.Get( nIndex
) );
596 //------------------------------------------------------------------
598 // function implementation starts here
600 //------------------------------------------------------------------
602 // auxiliary functions
604 sal_Bool
IsLeapYear( sal_uInt16 nYear
)
606 return ((((nYear
% 4) == 0) && ((nYear
% 100) != 0)) || ((nYear
% 400) == 0));
609 sal_uInt16
DaysInMonth( sal_uInt16 nMonth
, sal_uInt16 nYear
)
611 static sal_uInt16 aDaysInMonth
[12] = { 31, 28, 31, 30, 31, 30,
612 31, 31, 30, 31, 30, 31 };
615 return aDaysInMonth
[nMonth
-1];
618 if ( IsLeapYear(nYear
) )
619 return aDaysInMonth
[nMonth
-1] + 1;
621 return aDaysInMonth
[nMonth
-1];
626 * Convert a date to a count of days starting from 01/01/0001
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 converts a Day , Month, Year representation
631 * to this internal Date value.
634 sal_Int32
DateToDays( sal_uInt16 nDay
, sal_uInt16 nMonth
, sal_uInt16 nYear
)
636 sal_Int32 nDays
= ((sal_Int32
)nYear
-1) * 365;
637 nDays
+= ((nYear
-1) / 4) - ((nYear
-1) / 100) + ((nYear
-1) / 400);
639 for( sal_uInt16 i
= 1; i
< nMonth
; i
++ )
640 nDays
+= DaysInMonth(i
,nYear
);
647 * Convert a count of days starting from 01/01/0001 to a date
649 * The internal representation of a Date used in this Addin
650 * is the number of days between 01/01/0001 and the date
651 * this function converts this internal Date value
652 * to a Day , Month, Year representation of a Date.
655 void DaysToDate( sal_Int32 nDays
,
656 sal_uInt16
& rDay
, sal_uInt16
& rMonth
, sal_uInt16
& rYear
)
657 throw( lang::IllegalArgumentException
)
660 throw lang::IllegalArgumentException();
669 rYear
= (sal_uInt16
)((nTempDays
/ 365) - i
);
670 nTempDays
-= ((sal_Int32
) rYear
-1) * 365;
671 nTempDays
-= (( rYear
-1) / 4) - (( rYear
-1) / 100) + ((rYear
-1) / 400);
680 if ( nTempDays
> 365 )
682 if ( (nTempDays
!= 366) || !IsLeapYear( rYear
) )
693 while ( (sal_Int32
)nTempDays
> DaysInMonth( rMonth
, rYear
) )
695 nTempDays
-= DaysInMonth( rMonth
, rYear
);
698 rDay
= (sal_uInt16
)nTempDays
;
702 * Get the null date used by the spreadsheet document
704 * The internal representation of a Date used in this Addin
705 * is the number of days between 01/01/0001 and the date
706 * this function returns this internal Date value for the document null date
710 sal_Int32
GetNullDate( const uno::Reference
< beans::XPropertySet
>& xOptions
)
711 throw( uno::RuntimeException
)
717 uno::Any aAny
= xOptions
->getPropertyValue(
718 OUString::createFromAscii( "NullDate" ) );
720 if ( aAny
>>= aDate
)
721 return DateToDays( aDate
.Day
, aDate
.Month
, aDate
.Year
);
723 catch (uno::Exception
&)
728 // no null date available -> no calculations possible
729 throw uno::RuntimeException();
735 * Get week difference between 2 dates
737 * new Weeks(date1,date2,mode) function for StarCalc
739 * Two modes of operation are provided.
740 * The first is just a simple division by 7 calculation.
742 * The second calculates the diffence by week of year.
744 * The International Standard IS-8601 has decreed that Monday
745 * shall be the first day of the week.
747 * A week that lies partly in one year and partly in annother
748 * is assigned a number in the the year in which most of its days lie.
750 * That means that week 1 of any year is the week that contains the 4. January
752 * The internal representation of a Date used in the Addin is the number of days based on 01/01/0001
754 * A WeekDay can be then calculated by substracting 1 and calculating the rest of
755 * a division by 7, which gives a 0 - 6 value for Monday - Sunday
757 * Using the 4. January rule explained above the formula
759 * nWeek1= ( nDays1 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
761 * calculates a number between 0-53 for each day which is in the same year as nJan4
762 * where 0 means that this week belonged to the year before.
764 * If a day in the same or annother year is used in this formula this calculates
765 * an calendar week offset from a given 4. January
767 * nWeek2 = ( nDays2 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
769 * The 4.January of first Date Argument can thus be used to calculate
770 * the week difference by calendar weeks which is then nWeek = nWeek2 - nWeek1
772 * which can be optimized to
774 * nWeek = ( (nDays2-nJan4+((nJan4-1)%7))/7 ) - ( (nDays1-nJan4+((nJan4-1)%7))/7 )
776 * Note: All calculations are operating on the long integer data type
777 * % is the modulo operator in C which calculates the rest of an Integer division
780 * mode 0 is the interval between the dates in month, that is days / 7
782 * mode 1 is the difference by week of year
786 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffWeeks(
787 const uno::Reference
< beans::XPropertySet
>& xOptions
,
788 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
789 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
791 sal_Int32 nNullDate
= GetNullDate( xOptions
);
793 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
794 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
800 sal_uInt16 nDay
,nMonth
,nYear
;
801 DaysToDate( nDays1
, nDay
, nMonth
, nYear
);
802 sal_Int32 nJan4
= DateToDays( 4, 1, nYear
);
804 nRet
= ( (nDays2
-nJan4
+((nJan4
-1)%7))/7 ) - ( (nDays1
-nJan4
+((nJan4
-1)%7))/7 );
808 nRet
= (nDays2
- nDays1
) / 7;
814 * Get month difference between 2 dates
815 * =Month(start, end, mode) Function for StarCalc
817 * two modes are provided
819 * mode 0 is the interval between the dates in month
821 * mode 1 is the difference in calendar month
824 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffMonths(
825 const uno::Reference
< beans::XPropertySet
>& xOptions
,
826 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
827 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
829 sal_Int32 nNullDate
= GetNullDate( xOptions
);
831 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
832 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
834 sal_uInt16 nDay1
,nMonth1
,nYear1
;
835 sal_uInt16 nDay2
,nMonth2
,nYear2
;
836 DaysToDate(nDays1
,nDay1
,nMonth1
,nYear1
);
837 DaysToDate(nDays2
,nDay2
,nMonth2
,nYear2
);
839 sal_Int32 nRet
= nMonth2
- nMonth1
+ (nYear2
- nYear1
) * 12;
840 if ( nMode
== 1 || nDays1
== nDays2
) return nRet
;
842 if ( nDays1
< nDays2
)
861 * Get Year difference between 2 dates
863 * two modes are provided
865 * mode 0 is the interval between the dates in years
867 * mode 1 is the difference in calendar years
870 sal_Int32 SAL_CALL
ScaDateAddIn::getDiffYears(
871 const uno::Reference
< beans::XPropertySet
>& xOptions
,
872 sal_Int32 nStartDate
, sal_Int32 nEndDate
,
873 sal_Int32 nMode
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
876 return getDiffMonths( xOptions
, nStartDate
, nEndDate
, nMode
) / 12;
878 sal_Int32 nNullDate
= GetNullDate( xOptions
);
880 sal_Int32 nDays1
= nStartDate
+ nNullDate
;
881 sal_Int32 nDays2
= nEndDate
+ nNullDate
;
883 sal_uInt16 nDay1
,nMonth1
,nYear1
;
884 sal_uInt16 nDay2
,nMonth2
,nYear2
;
885 DaysToDate(nDays1
,nDay1
,nMonth1
,nYear1
);
886 DaysToDate(nDays2
,nDay2
,nMonth2
,nYear2
);
888 return nYear2
- nYear1
;
892 * Check if a Date is in a leap year in the Gregorian calendar
895 sal_Int32 SAL_CALL
ScaDateAddIn::getIsLeapYear(
896 const uno::Reference
< beans::XPropertySet
>& xOptions
,
897 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
899 sal_Int32 nNullDate
= GetNullDate( xOptions
);
900 sal_Int32 nDays
= nDate
+ nNullDate
;
902 sal_uInt16 nDay
, nMonth
, nYear
;
903 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
905 return (sal_Int32
)IsLeapYear(nYear
);
909 * Get the Number of Days in the month for a date
912 sal_Int32 SAL_CALL
ScaDateAddIn::getDaysInMonth(
913 const uno::Reference
<beans::XPropertySet
>& xOptions
,
914 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
916 sal_Int32 nNullDate
= GetNullDate( xOptions
);
917 sal_Int32 nDays
= nDate
+ nNullDate
;
919 sal_uInt16 nDay
, nMonth
, nYear
;
920 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
922 return DaysInMonth( nMonth
, nYear
);
926 * Get number of days in the year of a date specified
929 sal_Int32 SAL_CALL
ScaDateAddIn::getDaysInYear(
930 const uno::Reference
< beans::XPropertySet
>& xOptions
,
931 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
933 sal_Int32 nNullDate
= GetNullDate( xOptions
);
934 sal_Int32 nDays
= nDate
+ nNullDate
;
936 sal_uInt16 nDay
, nMonth
, nYear
;
937 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
939 return ( IsLeapYear(nYear
) ? 366 : 365 );
943 * Get number of weeks in the year for a date
945 * Most years have 52 weeks, but years that start on a Thursday
946 * and leep years that start on a Wednesday have 53 weeks
948 * The International Standard IS-8601 has decreed that Monday
949 * shall be the first day of the week.
951 * A WeekDay can be calculated by substracting 1 and calculating the rest of
952 * a division by 7 from the internal date represention
953 * which gives a 0 - 6 value for Monday - Sunday
955 * @see #IsLeapYear #WeekNumber
958 sal_Int32 SAL_CALL
ScaDateAddIn::getWeeksInYear(
959 const uno::Reference
< beans::XPropertySet
>& xOptions
,
960 sal_Int32 nDate
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
962 sal_Int32 nNullDate
= GetNullDate( xOptions
);
963 sal_Int32 nDays
= nDate
+ nNullDate
;
965 sal_uInt16 nDay
, nMonth
, nYear
;
966 DaysToDate(nDays
,nDay
,nMonth
,nYear
);
968 sal_Int32 nJan1WeekDay
= ( DateToDays(1,1,nYear
) - 1) % 7;
971 if ( nJan1WeekDay
== 3 ) /* Thursday */
973 else if ( nJan1WeekDay
== 2 ) /* Wednesday */
974 nRet
= ( IsLeapYear(nYear
) ? 53 : 52 );
982 * Encrypt or decrypt a string using ROT13 algorithm
984 * This function rotates each character by 13 in the alphabet.
985 * Only the characters 'a' ... 'z' and 'A' ... 'Z' are modified.
988 OUString SAL_CALL
ScaDateAddIn::getRot13( const OUString
& aSrcString
) throw( uno::RuntimeException
, lang::IllegalArgumentException
)
990 OUStringBuffer
aBuffer( aSrcString
);
991 for( sal_Int32 nIndex
= 0; nIndex
< aBuffer
.getLength(); nIndex
++ )
993 sal_Unicode cChar
= aBuffer
.charAt( nIndex
);
994 if( ((cChar
>= 'a') && (cChar
<= 'z') && ((cChar
+= 13) > 'z')) ||
995 ((cChar
>= 'A') && (cChar
<= 'Z') && ((cChar
+= 13) > 'Z')) )
997 aBuffer
.setCharAt( nIndex
, cChar
);
999 return aBuffer
.makeStringAndClear();
1002 //------------------------------------------------------------------