Update ooo320-m1
[ooovba.git] / scaddins / source / datefunc / datefunc.cxx
blobf01a3a6aeed544150601ec3469c32ee32aafb26d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: datefunc.cxx,v $
10 * $Revision: 1.16 $
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"
40 #endif
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;
66 ScaList::ScaList() :
67 pData( new void*[ nStartSize ] ),
68 nSize( nStartSize ),
69 nCount( 0 ),
70 nCurr( 0 )
74 ScaList::~ScaList()
76 delete[] pData;
79 void ScaList::_Grow()
81 nSize += nIncrSize;
83 void** pNewData = new void*[ nSize ];
84 memcpy( pNewData, pData, nCount * sizeof( void* ) );
86 delete[] pData;
87 pData = pNewData;
90 void ScaList::Insert( void* pNew, sal_uInt32 nIndex )
92 if( nIndex >= nCount )
93 Append( pNew );
94 else
96 Grow();
98 void** pIns = pData + nIndex;
99 memmove( pIns + 1, pIns, (nCount - nIndex) * sizeof( void* ) );
101 *pIns = pNew;
102 nCount++;
107 //------------------------------------------------------------------
109 ScaStringList::~ScaStringList()
111 for( OUString* pStr = First(); pStr; pStr = Next() )
112 delete pStr;
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 )
146 #undef FUNCDATA
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
174 if( !bWithOpt )
175 nParam++;
176 return (nParam > nParamCount) ? (nParamCount * 2) : (nParam * 2);
180 //------------------------------------------------------------------
182 ScaFuncDataList::ScaFuncDataList( ResMgr& rResMgr ) :
183 nLast( 0xFFFFFFFF )
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() )
194 delete pFData;
197 const ScaFuncData* ScaFuncDataList::Get( const OUString& rProgrammaticName ) const
199 if( aLastName == rProgrammaticName )
200 return Get( nLast );
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;
209 return pCurr;
212 return NULL;
216 //------------------------------------------------------------------
218 ScaFuncRes::ScaFuncRes( ResId& rResId, ResMgr& rResMgr, sal_uInt16 nIndex, OUString& rRet ) :
219 Resource( rResId )
221 rRet = String( ScaResId( nIndex, rResMgr ) );
222 FreeResource();
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();
236 return xInst;
240 //------------------------------------------------------------------------
242 extern "C" {
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 )
253 if (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] );
269 return sal_True;
271 catch (registry::InvalidRegistryException&)
273 OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
276 return sal_False;
279 void * SAL_CALL component_getFactory(
280 const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
282 void* pRet = 0;
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() ) );
293 if (xFactory.is())
295 xFactory->acquire();
296 pRet = xFactory.get();
300 return pRet;
303 } // extern C
305 //------------------------------------------------------------------------
307 // "normal" service implementation
309 //------------------------------------------------------------------------
311 ScaDateAddIn::ScaDateAddIn() :
312 pDefLocales( NULL ),
313 pResMgr( NULL ),
314 pFuncDataList( NULL )
318 ScaDateAddIn::~ScaDateAddIn()
320 if( pFuncDataList )
321 delete pFuncDataList;
322 if( pDefLocales )
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 )
345 if( !pDefLocales )
346 InitDefLocales();
348 return (nIndex < sizeof( pLang )) ? pDefLocales[ nIndex ] : aFuncLoc;
351 ResMgr& ScaDateAddIn::GetResMgr() throw( uno::RuntimeException )
353 if( !pResMgr )
355 InitData(); // try to get resource manager
356 if( !pResMgr )
357 throw uno::RuntimeException();
359 return *pResMgr;
362 void ScaDateAddIn::InitData()
364 if( pResMgr )
365 delete pResMgr;
367 OString aModName( "date" );
368 pResMgr = ResMgr::CreateResMgr( (const sal_Char*) aModName,
369 aFuncLoc );
371 if( pFuncDataList )
372 delete pFuncDataList;
374 pFuncDataList = pResMgr ? new ScaFuncDataList( *pResMgr ) : NULL;
376 if( pDefLocales )
378 delete pDefLocales;
379 pDefLocales = 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 )
390 OUString aRet;
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();
400 return aRet;
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 );
417 return aRet;
420 // XServiceName
422 OUString SAL_CALL ScaDateAddIn::getServiceName() throw( uno::RuntimeException )
424 // name of specific AddIn service
425 return OUString::createFromAscii( MY_SERVICE );
428 // XServiceInfo
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();
446 // XLocalizable
448 void SAL_CALL ScaDateAddIn::setLocale( const lang::Locale& eLocale ) throw( uno::RuntimeException )
450 aFuncLoc = eLocale;
451 InitData(); // change of locale invalidates resources!
454 lang::Locale SAL_CALL ScaDateAddIn::getLocale() throw( uno::RuntimeException )
456 return aFuncLoc;
459 //------------------------------------------------------------------
461 // function descriptions start here
463 //------------------------------------------------------------------
465 // XAddIn
467 OUString SAL_CALL ScaDateAddIn::getProgrammaticFuntionName( const OUString& ) throw( uno::RuntimeException )
469 // not used by calc
470 // (but should be implemented for other uses of the AddIn service)
471 return OUString();
474 OUString SAL_CALL ScaDateAddIn::getDisplayFunctionName( const OUString& aProgrammaticName ) throw( uno::RuntimeException )
476 OUString aRet;
478 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
479 if( pFData )
481 aRet = GetDisplFuncStr( pFData->GetUINameID() );
482 if( pFData->IsDouble() )
483 aRet += STR_FROM_ANSI( "_ADD" );
485 else
487 aRet = STR_FROM_ANSI( "UNKNOWNFUNC_" );
488 aRet += aProgrammaticName;
491 return aRet;
494 OUString SAL_CALL ScaDateAddIn::getFunctionDescription( const OUString& aProgrammaticName ) throw( uno::RuntimeException )
496 OUString aRet;
498 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
499 if( pFData )
500 aRet = GetFuncDescrStr( pFData->GetDescrID(), 1 );
502 return aRet;
505 OUString SAL_CALL ScaDateAddIn::getDisplayArgumentName(
506 const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException )
508 OUString aRet;
510 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
511 if( pFData && (nArgument <= 0xFFFF) )
513 sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
514 if( nStr )
515 aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr );
516 else
517 aRet = STR_FROM_ANSI( "internal" );
520 return aRet;
523 OUString SAL_CALL ScaDateAddIn::getArgumentDescription(
524 const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException )
526 OUString aRet;
528 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
529 if( pFData && (nArgument <= 0xFFFF) )
531 sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
532 if( nStr )
533 aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr + 1 );
534 else
535 aRet = STR_FROM_ANSI( "for internal use only" );
538 return aRet;
541 OUString SAL_CALL ScaDateAddIn::getProgrammaticCategoryName(
542 const OUString& aProgrammaticName ) throw( uno::RuntimeException )
544 OUString aRet;
546 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
547 if( pFData )
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
558 break;
562 if( !aRet.getLength() )
563 aRet = STR_FROM_ANSI( "Add-In" );
564 return aRet;
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 );
580 if( !pFData )
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 ) );
592 return aRet;
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 };
614 if ( nMonth != 2 )
615 return aDaysInMonth[nMonth-1];
616 else
618 if ( IsLeapYear(nYear) )
619 return aDaysInMonth[nMonth-1] + 1;
620 else
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);
641 nDays += nDay;
643 return nDays;
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 )
659 if( nDays < 0 )
660 throw lang::IllegalArgumentException();
662 sal_Int32 nTempDays;
663 sal_Int32 i = 0;
664 sal_Bool bCalc;
668 nTempDays = nDays;
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);
672 bCalc = sal_False;
673 if ( nTempDays < 1 )
675 i++;
676 bCalc = sal_True;
678 else
680 if ( nTempDays > 365 )
682 if ( (nTempDays != 366) || !IsLeapYear( rYear ) )
684 i--;
685 bCalc = sal_True;
690 while ( bCalc );
692 rMonth = 1;
693 while ( (sal_Int32)nTempDays > DaysInMonth( rMonth, rYear ) )
695 nTempDays -= DaysInMonth( rMonth, rYear );
696 rMonth++;
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 )
713 if (xOptions.is())
717 uno::Any aAny = xOptions->getPropertyValue(
718 OUString::createFromAscii( "NullDate" ) );
719 util::Date aDate;
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();
732 // XDateFunctions
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;
796 sal_Int32 nRet;
798 if ( nMode == 1 )
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 );
806 else
808 nRet = (nDays2 - nDays1) / 7;
810 return nRet;
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 )
844 if ( nDay1 > nDay2 )
846 nRet -= 1;
849 else
851 if ( nDay1 < nDay2 )
853 nRet += 1;
857 return nRet;
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 )
875 if ( nMode != 1 )
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;
970 sal_Int32 nRet;
971 if ( nJan1WeekDay == 3 ) /* Thursday */
972 nRet = 53;
973 else if ( nJan1WeekDay == 2 ) /* Wednesday */
974 nRet = ( IsLeapYear(nYear) ? 53 : 52 );
975 else
976 nRet = 52;
978 return nRet;
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')) )
996 cChar -= 26;
997 aBuffer.setCharAt( nIndex, cChar );
999 return aBuffer.makeStringAndClear();
1002 //------------------------------------------------------------------