Free RPG - Calculate prorated amount of annual premium, account for leap years

I need to calculate a prorated amount of annual premium in free rpgle and account the number of days in leap years.

say a company's annual premium would be $1000 and they sign up on 11/01. I only need to charge them for 61 days of the yearly premium.

anyone have any date math examples for doing this?
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Gary PattersonVP Technology / Senior Consultant Commented:
In what language?
Gary PattersonVP Technology / Senior Consultant Commented:

- Days from current date to end of current year.
values days(year(current_date) || '-12-31') - days (current_date);

- Days from DATE column
select days(year(current_date) || '-12-31') - days(PolicyEffectiveDate) as ProrateDays from sometable;

- Verify properly handles leap years, including special rules for years divisible by 100 and 400
values days('2016-03-01') - days ('2016-02-01')  --expect 29
values days('2017-01-01') - days ('2016-01-01')  -- normal leap year - expect 366
values days('1900-12-31') - days ('1899-12-31')  -- "100 rule" - expect 365
values days('2000-12-31') - days ('1999-12-31')  -- "400 rule" - expect 366

ILE RPG (didn't test, but hopefully you get the idea):

dcl-s endOfYear DATE(*ISO);
dcl-s effectiveDate DATE(*ISO) INZ('2017-03-17');
dcl-s proRateDays INT(5);

endOfYear = %date(%char(%subdt(%date() : *YEARS) :*ISO) || -12-31');
proRateDays = %diff( endOfYear : effectiveDate : *DAYS);
Gary PattersonVP Technology / Senior Consultant Commented:
Note that you need to know if it is a leap year or not to calculate that daily rate:

In a leap year, dailyRate = annualRate/366;
In a normal year, dailyRate = annualRate/365;

You can generalize:

dcl-s endOfThisYear DATE(*ISO);
dcl-s endOfLastYear DATE(*ISO);
dcl-s annualRate DEC(7 :2) INZ(1234.56)
dcl-s dailyRate DEC(9 : 4)

-- Get last day of this year
endOfThisYear = %date(%char(%subdt(%date() : *YEARS) :*ISO) || -12-31');
-- Get last day of last year
endOfLastYear = endOfThisYear - %years(1);
-- Divide by 365 in normal year, and 366 in leap year
dailyRate = annualRate / %diff(endOfThisYear : endOfLastYear : *DAYS);

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Become a Microsoft Certified Solutions Expert

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

Do you want it to be "61 days of a 365-day year because 2017 isn't a leap year" or "61 days of a 365.25-day year because that's a reasonable average over many years"? That is, do you want proration to be different for actual leap years or the same for every year?
Gary PattersonVP Technology / Senior Consultant Commented:
Since we're apparently dealing with some sort of insurance, it is possible that there is governing law that controls the calculation - and that could even vary by jurisdiction.  Might be tIme to email the legal team ...
Hi Roosterup, I see have your solution, but I would add a leap year checker like so:

 d Dec31PolYear s d
 d PolStrDate s d
 d LeapDay s 10
 d MultiPlier s 7 6  (7.6)
 d DaysLeftInYear s 3 0
 d OneYearPrimium s 10 2
 // Base Primium $10,0000 per year
     OneYearPrimium = 10000;
 // use %DIFF(Dec31CurYear : PolStrDate : *Days)
     Dec31PolYear = %Date(%CHAR(%SubDT(PolStrDate:*YEARS)) +
                                    '-12-31' : *iso);
     DaysLeftInYear = %DIFF(Dec31PolYear : PolStrDate : *Days) + 1;

   LeapDay = %CHAR(%SubDT(PolStrDate:*YEARS)) + '-02-29' ;
    test(ed) LeapDay;
    if Not %Error ;
       // It's a leap year
       MultiPlier = DaysLeftInYear / 366;
       // no Leap year
       MultiPlier = DaysLeftInYear / 365;

   OneYearPrimium = OneYearPrimium * MultiPler;
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
IBM System i

From novice to tech pro — start learning today.