For some reason I can't connect with gerrit, so I submit this patch in the classic way.
The patch improves the calculation of YEARFRAC in case of leap years.
There still is one more possible improvement (see ToDo-comment in patch), but that could be
argueable.
I'm interested in your opnions on that further improvement,
Eike, you will certainly have something to say about that.
Winfried
From a897334a5d183d24a2ec2dacfe50bf21239b78a6 Mon Sep 17 00:00:00 2001
From: Winfried Donkers <osc@dci-electronics>
Date: Thu, 11 Apr 2013 17:37:33 +0200
Subject: [PATCH] fdo#40100 correct result of calc function YEARFRAC
Change-Id: I8c27cf6ee942d42e8ca4d67a4c7665962094c4a1
---
scaddins/source/analysis/analysishelper.cxx | 31 +++++++++++++++++------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/scaddins/source/analysis/analysishelper.cxx
b/scaddins/source/analysis/analysishelper.cxx
index 27fea93..2b6c26e 100644
--- a/scaddins/source/analysis/analysishelper.cxx
+++ b/scaddins/source/analysis/analysishelper.cxx
@@ -366,21 +366,15 @@ void GetDiffParam( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32
nEndDate
nDay2, nMonth2, nYear2, nMode == 0 ) - nYears *
nDaysInYear;
break;
case 1: // 1=exact/exact
- nYears = nYear2 - nYear1;
+ //fdo40100 because of possible leap years calculate number
+ //of days separately for year1 and year2 and let nYears
+ //contain only number of full calendar years
+ nYears = nYear2 - nYear1 - 1;
nDaysInYear = IsLeapYear( nYear1 )? 366 : 365;
- if( nYears && ( nMonth1 > nMonth2 || ( nMonth1 == nMonth2 && nDay1 > nDay2 ) ) )
- nYears--;
-
- if( nYears )
- nDayDiff = nDate2 - DateToDays( nDay1, nMonth1, nYear2 );
- else
- nDayDiff = nDate2 - nDate1;
-
- if( nDayDiff < 0 )
- nDayDiff += nDaysInYear;
-
+ nDayDiff = ( nDate2 - DateToDays( 1, 1, nYear2 ) ) +
+ ( DateToDays( 31, 12, nYear1 ) - nDate1 ) + 1; //plus 1 for Dec 31 to Jan 1
break;
case 2: // 2=exact/360
nDaysInYear = 360;
@@ -508,6 +502,18 @@ sal_Int32 GetDaysInYear( sal_Int32 nNullDate, sal_Int32 nDate, sal_Int32 nMode
)
}
+//TODO: In the case of nMode == 1 (exact), there still remains a small error
+// in the result because of leap years. nDaysInYear is an integer and
+// returns the days in the year of nStartDate. If nEndDate is not a
+// leap year, the year fraction of the days in the year of nEndDate is
+// a little bit too small. If nStardate is not in a leap year, but
+// nEndDate is, then year fraction of the days in the year of nEndDate
+// is a little bit too large.
+// This could be corrected when nDaysInYear is a float and the value
+// reflects the number of days in the leap year and the non-leap year.
+// Example: If there are 80 days in the leap year and 80 days in the
+// non-leap year, then nDaysInYear would be 365.5, resulting in a more
+// or less exact year fraction.
double GetYearFrac( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDate, sal_Int32 nMode
) throw( uno::RuntimeException, lang::IllegalArgumentException )
{
if( nStartDate == nEndDate )
@@ -517,7 +523,6 @@ double GetYearFrac( sal_Int32 nNullDate, sal_Int32 nStartDate, sal_Int32 nEndDat
sal_Int32 nDayDiff, nDaysInYear;
GetDiffParam( nNullDate, nStartDate, nEndDate, nMode, nYears, nDayDiff, nDaysInYear );
-
return double( nYears ) + double( nDayDiff ) / double( nDaysInYear );
}
--
1.8.1.4
Context
- [PATCH] fdo#40100 correct result of calc function YEARFRAC · Winfried Donkers
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.