Bump version to 5.0-14
[LibreOffice.git] / scaddins / source / datefunc / datefunc.cxx
blobadfd32fda8599830c27702852c61b7fb43d3aecc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 #include "datefunc.hxx"
21 #include "datefunc.hrc"
22 #include <com/sun/star/util/Date.hpp>
23 #include <cppuhelper/factory.hxx>
24 #include <cppuhelper/supportsservice.hxx>
25 #include <osl/diagnose.h>
26 #include <rtl/ustrbuf.hxx>
27 #include <tools/rcid.h>
28 #include <tools/resmgr.hxx>
30 using namespace ::com::sun::star;
32 #define ADDIN_SERVICE "com.sun.star.sheet.AddIn"
33 #define MY_SERVICE "com.sun.star.sheet.addin.DateFunctions"
34 #define MY_IMPLNAME "com.sun.star.sheet.addin.DateFunctionsImpl"
36 #define STR_FROM_ANSI( s ) OUString( s, strlen( s ), RTL_TEXTENCODING_MS_1252 )
38 const sal_uInt32 ScaList::nStartSize = 16;
39 const sal_uInt32 ScaList::nIncrSize = 16;
41 ScaList::ScaList() :
42 pData( new void*[ nStartSize ] ),
43 nSize( nStartSize ),
44 nCount( 0 ),
45 nCurr( 0 )
49 ScaList::~ScaList()
51 delete[] pData;
54 void ScaList::_Grow()
56 nSize += nIncrSize;
58 void** pNewData = new void*[ nSize ];
59 memcpy( pNewData, pData, nCount * sizeof( void* ) );
61 delete[] pData;
62 pData = pNewData;
65 ScaStringList::~ScaStringList()
67 for( OUString* pStr = First(); pStr; pStr = Next() )
68 delete pStr;
71 ScaResId::ScaResId( sal_uInt16 nId, ResMgr& rResMgr ) :
72 ResId( nId, rResMgr )
76 #define UNIQUE false // function name does not exist in Calc
78 #define STDPAR false // all parameters are described
79 #define INTPAR true // first parameter is internal
81 #define FUNCDATA( FuncName, ParamCount, Category, Double, IntPar ) \
82 { "get" #FuncName, DATE_FUNCNAME_##FuncName, DATE_FUNCDESC_##FuncName, DATE_DEFFUNCNAME_##FuncName, ParamCount, Category, Double, IntPar }
84 const ScaFuncDataBase pFuncDataArr[] =
86 FUNCDATA( DiffWeeks, 3, ScaCat_DateTime, UNIQUE, INTPAR ),
87 FUNCDATA( DiffMonths, 3, ScaCat_DateTime, UNIQUE, INTPAR ),
88 FUNCDATA( DiffYears, 3, ScaCat_DateTime, UNIQUE, INTPAR ),
89 FUNCDATA( IsLeapYear, 1, ScaCat_DateTime, UNIQUE, INTPAR ),
90 FUNCDATA( DaysInMonth, 1, ScaCat_DateTime, UNIQUE, INTPAR ),
91 FUNCDATA( DaysInYear, 1, ScaCat_DateTime, UNIQUE, INTPAR ),
92 FUNCDATA( WeeksInYear, 1, ScaCat_DateTime, UNIQUE, INTPAR ),
93 FUNCDATA( Rot13, 1, ScaCat_Text, UNIQUE, STDPAR )
96 #undef FUNCDATA
98 ScaFuncData::ScaFuncData( const ScaFuncDataBase& rBaseData, ResMgr& rResMgr ) :
99 aIntName( OUString::createFromAscii( rBaseData.pIntName ) ),
100 nUINameID( rBaseData.nUINameID ),
101 nDescrID( rBaseData.nDescrID ),
102 nCompListID( rBaseData.nCompListID ),
103 nParamCount( rBaseData.nParamCount ),
104 eCat( rBaseData.eCat ),
105 bDouble( rBaseData.bDouble ),
106 bWithOpt( rBaseData.bWithOpt )
108 ScaResStringArrLoader aArrLoader( RID_DATE_DEFFUNCTION_NAMES, nCompListID, rResMgr );
109 const ResStringArray& rArr = aArrLoader.GetStringArray();
111 for( sal_uInt16 nIndex = 0; nIndex < rArr.Count(); nIndex++ )
112 aCompList.Append( rArr.GetString( nIndex ) );
115 ScaFuncData::~ScaFuncData()
119 sal_uInt16 ScaFuncData::GetStrIndex( sal_uInt16 nParam ) const
121 if( !bWithOpt )
122 nParam++;
123 return (nParam > nParamCount) ? (nParamCount * 2) : (nParam * 2);
127 ScaFuncDataList::ScaFuncDataList( ResMgr& rResMgr ) :
128 nLast( 0xFFFFFFFF )
130 for( sal_uInt16 nIndex = 0; nIndex < SAL_N_ELEMENTS(pFuncDataArr); nIndex++ )
131 Append( new ScaFuncData( pFuncDataArr[ nIndex ], rResMgr ) );
134 ScaFuncDataList::~ScaFuncDataList()
136 for( ScaFuncData* pFData = First(); pFData; pFData = Next() )
137 delete pFData;
140 const ScaFuncData* ScaFuncDataList::Get( const OUString& rProgrammaticName ) const
142 if( aLastName == rProgrammaticName )
143 return Get( nLast );
145 for( sal_uInt32 nIndex = 0; nIndex < Count(); nIndex++ )
147 const ScaFuncData* pCurr = Get( nIndex );
148 if( pCurr->Is( rProgrammaticName ) )
150 const_cast< ScaFuncDataList* >( this )->aLastName = rProgrammaticName;
151 const_cast< ScaFuncDataList* >( this )->nLast = nIndex;
152 return pCurr;
155 return NULL;
158 ScaFuncRes::ScaFuncRes( ResId& rResId, ResMgr& rResMgr, sal_uInt16 nIndex, OUString& rRet ) :
159 Resource( rResId )
161 rRet = ScaResId(nIndex, rResMgr).toString();
162 FreeResource();
165 // entry points for service registration / instantiation
166 uno::Reference< uno::XInterface > SAL_CALL ScaDateAddIn_CreateInstance(
167 const uno::Reference< lang::XMultiServiceFactory >& )
169 return (cppu::OWeakObject*) new ScaDateAddIn();
172 extern "C" {
174 SAL_DLLPUBLIC_EXPORT void * SAL_CALL date_component_getFactory(
175 const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
177 void* pRet = 0;
179 if ( pServiceManager &&
180 OUString::createFromAscii( pImplName ) == ScaDateAddIn::getImplementationName_Static() )
182 uno::Reference< lang::XSingleServiceFactory > xFactory( cppu::createOneInstanceFactory(
183 static_cast< lang::XMultiServiceFactory* >( pServiceManager ),
184 ScaDateAddIn::getImplementationName_Static(),
185 ScaDateAddIn_CreateInstance,
186 ScaDateAddIn::getSupportedServiceNames_Static() ) );
188 if (xFactory.is())
190 xFactory->acquire();
191 pRet = xFactory.get();
195 return pRet;
198 } // extern C
200 // "normal" service implementation
201 ScaDateAddIn::ScaDateAddIn() :
202 pDefLocales( NULL ),
203 pResMgr( NULL ),
204 pFuncDataList( NULL )
208 ScaDateAddIn::~ScaDateAddIn()
210 delete pFuncDataList;
211 delete pResMgr;
212 delete[] pDefLocales;
215 static const sal_Char* pLang[] = { "de", "en" };
216 static const sal_Char* pCoun[] = { "DE", "US" };
217 static const sal_uInt32 nNumOfLoc = SAL_N_ELEMENTS( pLang );
219 void ScaDateAddIn::InitDefLocales()
221 pDefLocales = new lang::Locale[ nNumOfLoc ];
223 for( sal_uInt32 nIndex = 0; nIndex < nNumOfLoc; nIndex++ )
225 pDefLocales[ nIndex ].Language = OUString::createFromAscii( pLang[ nIndex ] );
226 pDefLocales[ nIndex ].Country = OUString::createFromAscii( pCoun[ nIndex ] );
230 const lang::Locale& ScaDateAddIn::GetLocale( sal_uInt32 nIndex )
232 if( !pDefLocales )
233 InitDefLocales();
235 return (nIndex < sizeof( pLang )) ? pDefLocales[ nIndex ] : aFuncLoc;
238 ResMgr& ScaDateAddIn::GetResMgr() throw( uno::RuntimeException )
240 if( !pResMgr )
242 InitData(); // try to get resource manager
243 if( !pResMgr )
244 throw uno::RuntimeException();
246 return *pResMgr;
249 void ScaDateAddIn::InitData()
251 delete pResMgr;
252 pResMgr = ResMgr::CreateResMgr("date", LanguageTag(aFuncLoc));
253 delete pFuncDataList;
255 pFuncDataList = pResMgr ? new ScaFuncDataList( *pResMgr ) : NULL;
257 if( pDefLocales )
259 delete pDefLocales;
260 pDefLocales = NULL;
264 OUString ScaDateAddIn::GetDisplFuncStr( sal_uInt16 nResId ) throw( uno::RuntimeException )
266 return ScaResStringLoader( RID_DATE_FUNCTION_NAMES, nResId, GetResMgr() ).GetString();
269 OUString ScaDateAddIn::GetFuncDescrStr( sal_uInt16 nResId, sal_uInt16 nStrIndex ) throw( uno::RuntimeException )
271 OUString aRet;
273 ScaResPublisher aResPubl( ScaResId( RID_DATE_FUNCTION_DESCRIPTIONS, GetResMgr() ) );
274 ScaResId aResId( nResId, GetResMgr() );
275 aResId.SetRT( RSC_RESOURCE );
277 if( aResPubl.IsAvailableRes( aResId ) )
278 ScaFuncRes aSubRes( aResId, GetResMgr(), nStrIndex, aRet );
280 aResPubl.FreeResource();
281 return aRet;
284 OUString ScaDateAddIn::getImplementationName_Static()
286 return OUString( MY_IMPLNAME );
289 uno::Sequence< OUString > ScaDateAddIn::getSupportedServiceNames_Static()
291 uno::Sequence< OUString > aRet( 2 );
292 OUString* pArray = aRet.getArray();
293 pArray[0] = ADDIN_SERVICE;
294 pArray[1] = MY_SERVICE;
295 return aRet;
298 // XServiceName
299 OUString SAL_CALL ScaDateAddIn::getServiceName() throw( uno::RuntimeException, std::exception )
301 // name of specific AddIn service
302 return OUString( MY_SERVICE );
305 // XServiceInfo
306 OUString SAL_CALL ScaDateAddIn::getImplementationName() throw( uno::RuntimeException, std::exception )
308 return getImplementationName_Static();
311 sal_Bool SAL_CALL ScaDateAddIn::supportsService( const OUString& aServiceName ) throw( uno::RuntimeException, std::exception )
313 return cppu::supportsService(this, aServiceName);
316 uno::Sequence< OUString > SAL_CALL ScaDateAddIn::getSupportedServiceNames() throw( uno::RuntimeException, std::exception )
318 return getSupportedServiceNames_Static();
321 // XLocalizable
322 void SAL_CALL ScaDateAddIn::setLocale( const lang::Locale& eLocale ) throw( uno::RuntimeException, std::exception )
324 aFuncLoc = eLocale;
325 InitData(); // change of locale invalidates resources!
328 lang::Locale SAL_CALL ScaDateAddIn::getLocale() throw( uno::RuntimeException, std::exception )
330 return aFuncLoc;
333 OUString SAL_CALL ScaDateAddIn::getProgrammaticFuntionName( const OUString& ) throw( uno::RuntimeException, std::exception )
335 // not used by calc
336 // (but should be implemented for other uses of the AddIn service)
337 return OUString();
340 OUString SAL_CALL ScaDateAddIn::getDisplayFunctionName( const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
342 OUString aRet;
344 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
345 if( pFData )
347 aRet = GetDisplFuncStr( pFData->GetUINameID() );
348 if( pFData->IsDouble() )
349 aRet += STR_FROM_ANSI( "_ADD" );
351 else
353 aRet = STR_FROM_ANSI( "UNKNOWNFUNC_" );
354 aRet += aProgrammaticName;
357 return aRet;
360 OUString SAL_CALL ScaDateAddIn::getFunctionDescription( const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
362 OUString aRet;
364 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
365 if( pFData )
366 aRet = GetFuncDescrStr( pFData->GetDescrID(), 1 );
368 return aRet;
371 OUString SAL_CALL ScaDateAddIn::getDisplayArgumentName(
372 const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException, std::exception )
374 OUString aRet;
376 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
377 if( pFData && (nArgument <= 0xFFFF) )
379 sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
380 if( nStr )
381 aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr );
382 else
383 aRet = STR_FROM_ANSI( "internal" );
386 return aRet;
389 OUString SAL_CALL ScaDateAddIn::getArgumentDescription(
390 const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException, std::exception )
392 OUString aRet;
394 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
395 if( pFData && (nArgument <= 0xFFFF) )
397 sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
398 if( nStr )
399 aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr + 1 );
400 else
401 aRet = STR_FROM_ANSI( "for internal use only" );
404 return aRet;
407 OUString SAL_CALL ScaDateAddIn::getProgrammaticCategoryName(
408 const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
410 OUString aRet;
412 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
413 if( pFData )
415 switch( pFData->GetCategory() )
417 case ScaCat_DateTime: aRet = STR_FROM_ANSI( "Date&Time" ); break;
418 case ScaCat_Text: aRet = STR_FROM_ANSI( "Text" ); break;
419 case ScaCat_Finance: aRet = STR_FROM_ANSI( "Financial" ); break;
420 case ScaCat_Inf: aRet = STR_FROM_ANSI( "Information" ); break;
421 case ScaCat_Math: aRet = STR_FROM_ANSI( "Mathematical" ); break;
422 case ScaCat_Tech: aRet = STR_FROM_ANSI( "Technical" ); break;
423 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
424 default:
425 break;
429 if( aRet.isEmpty() )
430 aRet = STR_FROM_ANSI( "Add-In" );
431 return aRet;
434 OUString SAL_CALL ScaDateAddIn::getDisplayCategoryName(
435 const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
437 return getProgrammaticCategoryName( aProgrammaticName );
440 // XCompatibilityNames
441 uno::Sequence< sheet::LocalizedName > SAL_CALL ScaDateAddIn::getCompatibilityNames(
442 const OUString& aProgrammaticName ) throw( uno::RuntimeException, std::exception )
444 const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
445 if( !pFData )
446 return uno::Sequence< sheet::LocalizedName >( 0 );
448 const ScaStringList& rStrList = pFData->GetCompNameList();
449 sal_uInt32 nCount = rStrList.Count();
451 uno::Sequence< sheet::LocalizedName > aRet( nCount );
452 sheet::LocalizedName* pArray = aRet.getArray();
454 for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
455 pArray[ nIndex ] = sheet::LocalizedName( GetLocale( nIndex ), *rStrList.Get( nIndex ) );
457 return aRet;
460 namespace {
462 // auxiliary functions
463 bool IsLeapYear( sal_uInt16 nYear )
465 return ((((nYear % 4) == 0) && ((nYear % 100) != 0)) || ((nYear % 400) == 0));
468 sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear )
470 static const sal_uInt16 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30,
471 31, 31, 30, 31, 30, 31 };
473 if ( nMonth != 2 )
474 return aDaysInMonth[nMonth-1];
475 else
477 if ( IsLeapYear(nYear) )
478 return aDaysInMonth[nMonth-1] + 1;
479 else
480 return aDaysInMonth[nMonth-1];
485 * Convert a date to a count of days starting from 01/01/0001
487 * The internal representation of a Date used in this Addin
488 * is the number of days between 01/01/0001 and the date
489 * this function converts a Day , Month, Year representation
490 * to this internal Date value.
493 sal_Int32 DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear )
495 sal_Int32 nDays = ((sal_Int32)nYear-1) * 365;
496 nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400);
498 for( sal_uInt16 i = 1; i < nMonth; i++ )
499 nDays += DaysInMonth(i,nYear);
500 nDays += nDay;
502 return nDays;
506 * Convert a count of days starting from 01/01/0001 to a date
508 * The internal representation of a Date used in this Addin
509 * is the number of days between 01/01/0001 and the date
510 * this function converts this internal Date value
511 * to a Day , Month, Year representation of a Date.
514 void DaysToDate( sal_Int32 nDays,
515 sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear )
516 throw( lang::IllegalArgumentException )
518 if( nDays < 0 )
519 throw lang::IllegalArgumentException();
521 sal_Int32 nTempDays;
522 sal_Int32 i = 0;
523 bool bCalc;
527 nTempDays = nDays;
528 rYear = (sal_uInt16)((nTempDays / 365) - i);
529 nTempDays -= ((sal_Int32) rYear -1) * 365;
530 nTempDays -= (( rYear -1) / 4) - (( rYear -1) / 100) + ((rYear -1) / 400);
531 bCalc = false;
532 if ( nTempDays < 1 )
534 i++;
535 bCalc = true;
537 else
539 if ( nTempDays > 365 )
541 if ( (nTempDays != 366) || !IsLeapYear( rYear ) )
543 i--;
544 bCalc = true;
549 while ( bCalc );
551 rMonth = 1;
552 while ( (sal_Int32)nTempDays > DaysInMonth( rMonth, rYear ) )
554 nTempDays -= DaysInMonth( rMonth, rYear );
555 rMonth++;
557 rDay = (sal_uInt16)nTempDays;
561 * Get the null date used by the spreadsheet document
563 * The internal representation of a Date used in this Addin
564 * is the number of days between 01/01/0001 and the date
565 * this function returns this internal Date value for the document null date
568 sal_Int32 GetNullDate( const uno::Reference< beans::XPropertySet >& xOptions )
569 throw( uno::RuntimeException )
571 if (xOptions.is())
575 uno::Any aAny = xOptions->getPropertyValue(
576 OUString( "NullDate" ) );
577 util::Date aDate;
578 if ( aAny >>= aDate )
579 return DateToDays( aDate.Day, aDate.Month, aDate.Year );
581 catch (uno::Exception&)
586 // no null date available -> no calculations possible
587 throw uno::RuntimeException();
591 // XDateFunctions
594 * Get week difference between 2 dates
596 * new Weeks(date1,date2,mode) function for StarCalc
598 * Two modes of operation are provided.
599 * The first is just a simple division by 7 calculation.
601 * The second calculates the diffence by week of year.
603 * The International Standard IS-8601 has decreed that Monday
604 * shall be the first day of the week.
606 * A week that lies partly in one year and partly in annother
607 * is assigned a number in the year in which most of its days lie.
609 * That means that week 1 of any year is the week that contains the 4. January
611 * The internal representation of a Date used in the Addin is the number of days based on 01/01/0001
613 * A WeekDay can be then calculated by subtracting 1 and calculating the rest of
614 * a division by 7, which gives a 0 - 6 value for Monday - Sunday
616 * Using the 4. January rule explained above the formula
618 * nWeek1= ( nDays1 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
620 * calculates a number between 0-53 for each day which is in the same year as nJan4
621 * where 0 means that this week belonged to the year before.
623 * If a day in the same or another year is used in this formula this calculates
624 * an calendar week offset from a given 4. January
626 * nWeek2 = ( nDays2 - nJan4 + ( (nJan4-1) % 7 ) ) / 7 + 1;
628 * The 4.January of first Date Argument can thus be used to calculate
629 * the week difference by calendar weeks which is then nWeek = nWeek2 - nWeek1
631 * which can be optimized to
633 * nWeek = ( (nDays2-nJan4+((nJan4-1)%7))/7 ) - ( (nDays1-nJan4+((nJan4-1)%7))/7 )
635 * Note: All calculations are operating on the long integer data type
636 * % is the modulo operator in C which calculates the rest of an Integer division
639 * mode 0 is the interval between the dates in month, that is days / 7
641 * mode 1 is the difference by week of year
645 sal_Int32 SAL_CALL ScaDateAddIn::getDiffWeeks(
646 const uno::Reference< beans::XPropertySet >& xOptions,
647 sal_Int32 nStartDate, sal_Int32 nEndDate,
648 sal_Int32 nMode ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
650 sal_Int32 nNullDate = GetNullDate( xOptions );
652 sal_Int32 nDays1 = nStartDate + nNullDate;
653 sal_Int32 nDays2 = nEndDate + nNullDate;
655 sal_Int32 nRet;
657 if ( nMode == 1 )
659 sal_uInt16 nDay,nMonth,nYear;
660 DaysToDate( nDays1, nDay, nMonth, nYear );
661 sal_Int32 nJan4 = DateToDays( 4, 1, nYear );
663 nRet = ( (nDays2-nJan4+((nJan4-1)%7))/7 ) - ( (nDays1-nJan4+((nJan4-1)%7))/7 );
665 else
667 nRet = (nDays2 - nDays1) / 7;
669 return nRet;
673 * Get month difference between 2 dates
674 * =Month(start, end, mode) Function for StarCalc
676 * two modes are provided
678 * mode 0 is the interval between the dates in month
680 * mode 1 is the difference in calendar month
682 sal_Int32 SAL_CALL ScaDateAddIn::getDiffMonths(
683 const uno::Reference< beans::XPropertySet >& xOptions,
684 sal_Int32 nStartDate, sal_Int32 nEndDate,
685 sal_Int32 nMode ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
687 sal_Int32 nNullDate = GetNullDate( xOptions );
689 sal_Int32 nDays1 = nStartDate + nNullDate;
690 sal_Int32 nDays2 = nEndDate + nNullDate;
692 sal_uInt16 nDay1,nMonth1,nYear1;
693 sal_uInt16 nDay2,nMonth2,nYear2;
694 DaysToDate(nDays1,nDay1,nMonth1,nYear1);
695 DaysToDate(nDays2,nDay2,nMonth2,nYear2);
697 sal_Int32 nRet = nMonth2 - nMonth1 + (nYear2 - nYear1) * 12;
698 if ( nMode == 1 || nDays1 == nDays2 ) return nRet;
700 if ( nDays1 < nDays2 )
702 if ( nDay1 > nDay2 )
704 nRet -= 1;
707 else
709 if ( nDay1 < nDay2 )
711 nRet += 1;
715 return nRet;
719 * Get Year difference between 2 dates
721 * two modes are provided
723 * mode 0 is the interval between the dates in years
725 * mode 1 is the difference in calendar years
727 sal_Int32 SAL_CALL ScaDateAddIn::getDiffYears(
728 const uno::Reference< beans::XPropertySet >& xOptions,
729 sal_Int32 nStartDate, sal_Int32 nEndDate,
730 sal_Int32 nMode ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
732 if ( nMode != 1 )
733 return getDiffMonths( xOptions, nStartDate, nEndDate, nMode ) / 12;
735 sal_Int32 nNullDate = GetNullDate( xOptions );
737 sal_Int32 nDays1 = nStartDate + nNullDate;
738 sal_Int32 nDays2 = nEndDate + nNullDate;
740 sal_uInt16 nDay1,nMonth1,nYear1;
741 sal_uInt16 nDay2,nMonth2,nYear2;
742 DaysToDate(nDays1,nDay1,nMonth1,nYear1);
743 DaysToDate(nDays2,nDay2,nMonth2,nYear2);
745 return nYear2 - nYear1;
749 * Check if a Date is in a leap year in the Gregorian calendar
751 sal_Int32 SAL_CALL ScaDateAddIn::getIsLeapYear(
752 const uno::Reference< beans::XPropertySet >& xOptions,
753 sal_Int32 nDate ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
755 sal_Int32 nNullDate = GetNullDate( xOptions );
756 sal_Int32 nDays = nDate + nNullDate;
758 sal_uInt16 nDay, nMonth, nYear;
759 DaysToDate(nDays,nDay,nMonth,nYear);
761 return (sal_Int32)IsLeapYear(nYear);
765 * Get the Number of Days in the month for a date
767 sal_Int32 SAL_CALL ScaDateAddIn::getDaysInMonth(
768 const uno::Reference<beans::XPropertySet>& xOptions,
769 sal_Int32 nDate ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
771 sal_Int32 nNullDate = GetNullDate( xOptions );
772 sal_Int32 nDays = nDate + nNullDate;
774 sal_uInt16 nDay, nMonth, nYear;
775 DaysToDate(nDays,nDay,nMonth,nYear);
777 return DaysInMonth( nMonth, nYear );
781 * Get number of days in the year of a date specified
783 sal_Int32 SAL_CALL ScaDateAddIn::getDaysInYear(
784 const uno::Reference< beans::XPropertySet >& xOptions,
785 sal_Int32 nDate ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
787 sal_Int32 nNullDate = GetNullDate( xOptions );
788 sal_Int32 nDays = nDate + nNullDate;
790 sal_uInt16 nDay, nMonth, nYear;
791 DaysToDate(nDays,nDay,nMonth,nYear);
793 return ( IsLeapYear(nYear) ? 366 : 365 );
797 * Get number of weeks in the year for a date
799 * Most years have 52 weeks, but years that start on a Thursday
800 * and leep years that start on a Wednesday have 53 weeks
802 * The International Standard IS-8601 has decreed that Monday
803 * shall be the first day of the week.
805 * A WeekDay can be calculated by subtracting 1 and calculating the rest of
806 * a division by 7 from the internal date represention
807 * which gives a 0 - 6 value for Monday - Sunday
809 * @see #IsLeapYear #WeekNumber
811 sal_Int32 SAL_CALL ScaDateAddIn::getWeeksInYear(
812 const uno::Reference< beans::XPropertySet >& xOptions,
813 sal_Int32 nDate ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
815 sal_Int32 nNullDate = GetNullDate( xOptions );
816 sal_Int32 nDays = nDate + nNullDate;
818 sal_uInt16 nDay, nMonth, nYear;
819 DaysToDate(nDays,nDay,nMonth,nYear);
821 sal_Int32 nJan1WeekDay = ( DateToDays(1,1,nYear) - 1) % 7;
823 sal_Int32 nRet;
824 if ( nJan1WeekDay == 3 ) /* Thursday */
825 nRet = 53;
826 else if ( nJan1WeekDay == 2 ) /* Wednesday */
827 nRet = ( IsLeapYear(nYear) ? 53 : 52 );
828 else
829 nRet = 52;
831 return nRet;
835 * Encrypt or decrypt a string using ROT13 algorithm
837 * This function rotates each character by 13 in the alphabet.
838 * Only the characters 'a' ... 'z' and 'A' ... 'Z' are modified.
840 OUString SAL_CALL ScaDateAddIn::getRot13( const OUString& aSrcString ) throw( uno::RuntimeException, lang::IllegalArgumentException, std::exception )
842 OUStringBuffer aBuffer( aSrcString );
843 for( sal_Int32 nIndex = 0; nIndex < aBuffer.getLength(); nIndex++ )
845 sal_Unicode cChar = aBuffer[nIndex];
846 if( ((cChar >= 'a') && (cChar <= 'z') && ((cChar += 13) > 'z')) ||
847 ((cChar >= 'A') && (cChar <= 'Z') && ((cChar += 13) > 'Z')) )
848 cChar -= 26;
849 aBuffer[nIndex] = cChar;
851 return aBuffer.makeStringAndClear();
854 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */