Waysys on the Web

Insurance Date Calculations

Insurance Date Calculations

Previous topic Next topic  

Insurance Date Calculations

Previous topic Next topic  

(*

 

Class:      InsureDate

Package:    com.waysysweb.util

Author:     W. Shaffer

Date:       07-Jan-2007

Description:

 

   This structure specifies various date calculations useful in insurance

   applications.

 

Maintenance:

 

Date        Author  Description

----------- ------  -----------------------------------------------------------

07-Jan-2007 Shaffer File created

 

*)

 

structure INSUREDATE = struct

 

    (*============  Exceptions ==============================================*)

 

    exception InsureDateError;

 

    (*============  Imports     =============================================*)

 

    (* Date Imports                                                          *)

    type WayDate = WAYDATE.WayDate;

    type Month   = WAYDATE.Month;

    type Day     = WAYDATE.Day;

    type Year    = WAYDATE.Year;

    

    fun getDay(date : WayDate) : Day = WAYDATE.getDay(date);

    fun getMonth(date : WayDate) : Month = WAYDATE.getMonth(date);

    fun getYear(date : WayDate) : Year  = WAYDATE.getYear(date);

    fun compare(date1 : WayDate, date2 : WayDate) : order =

        WAYDATE.compare(date1, date2);

    fun daysInMonth(mnth : Month, yr : Year) : Day =

        WAYDATE.daysInMonth(mnth, yr);

    fun difference(date1 : WayDate, date2 : WayDate)  : int =

        WAYDATE.difference(date1, date2);

    

    (*============  Types       =============================================*)

 

 

 

    (*============  Constants  ==============================================*)

 

    val MaxDate = WAYDATE.MaxDate;

    

    val MinDate = WAYDATE.MinDate;

    

    val MaxYear = WAYDATE.MaxYear;

    

    val MinYear = WAYDATE.MinYear;

 

    (*============  Properties ==============================================*)

 

 

 

    (*============  Attributes  =============================================*)

 

 

 

    (*============  Invariant   =============================================*)

 

 

 

    (*============  Initialization ==========================================*)

 

    (* Create a date *)

    (* Precondition:  (none)                                                  *)

    fun create(mnth : Month, dy : Day, yr : Year) : WayDate = 

        WAYDATE.create(mnth, dy, yr);

 

    (*============  Operations  =============================================*)

 

    (* Return the age *)

    fun age(laterDate : WayDate, earlierDate : WayDate) : int =

        if (compare(laterDate, earlierDate) = LESS)

        then raise InsureDateError

        else

           let

              val laterMonth = getMonth(laterDate);

              val laterDay = getDay(laterDate);

              val earlierMonth = getMonth(earlierDate);

              val earlierDay = getDay(earlierDate);

              val laterYear = getYear(laterDate);

              val earlierYear = getYear(earlierDate)

           in

              if  laterMonth >  earlierMonth

              then laterYear - earlierYear

              else if (laterMonth =  earlierMonth) andalso (laterDay >= earlierDay)

              then laterYear - earlierYear

              else laterYear - earlierYear - 1

           end;

 

    (* add one month to a date                                               *)

    fun nextMonth(date : WayDate) : WayDate =

        if getMonth(date) = 12 andalso getYear(date) = MaxYear then

            raise InsureDateError

        else

            let

                val day         = getDay(date);

                val month       = getMonth(date);

                val year        = getYear(date);

                val nextMonth   = if month = 12 then 1

                                  else month + 1;

                val nextYear    = if month = 12 then year + 1

                                  else               year;

                val daysInMonth = daysInMonth(nextMonth, nextYear);

                val nextDay     = int.min(day, daysInMonth)

            in

                create(nextMonth, nextDay, nextYear)

            end;

 

     (* Return a date after adding a number of months                         *)

     fun addMonths(date : WayDate, months : int) : WayDate =

              if months < 0 then raise InsureDateError

         else if months = 0 then date

         else                    addMonths(nextMonth(date), months - 1);

 

     (* add a number of years to a date                                      *)

     (*    NOTE: the date cannot be a leap day                               *)

     fun addYears(date : WayDate, years : int) : WayDate =

         let

            val month = getMonth(date);

            val day   = getDay(date);

            val year  = getYear(date);

         in

            if      year + years > MaxYear     then raise InsureDateError

            else if year + years < MinYear     then raise InsureDateError

            else if month = 2 andalso day = 29 then raise InsureDateError

            else create(month, day, year + years)

         end;

 

    (* return the number of days in a year a certain number of years from    *)

    (* a beginning date (e.g. issue date)                                    *)

    fun daysInPolicyYear(effectiveDate : WayDate, polYear : int) : int =

        let

            val beginPolYear = addYears(effectiveDate, polYear);

            val endPolYear   = addYears(beginPolYear, 1)

        in

            difference(endPolYear, beginPolYear)

        end;

 

    (* return the number of days in the month                               *)

    fun daysInPolicyMonth(monthaversary : WayDate) : int =

        let

            val next = nextMonth(monthaversary)

        in

            difference(next, monthaversary)

        end;

 

    (* return the number of months between a base date and a new date        *)

    fun diffMonths(newDate : WayDate, baseDate : WayDate) : int =

        let

            val ord = compare(baseDate, newDate)

        in

                 if ord = LESS  then 1 + diffMonths(newDate, nextMonth(baseDate))

            else if ord = EQUAL then 0

            else                     ~1

        end;

 

    (* return the number of years between a base date and a new date         *)

    fun diffYears(newDate : WayDate, baseDate : WayDate) : int =

        let

            val comp = compare(baseDate, newDate)

        in

            case comp of

                 LESS    => 1 + diffYears(newDate, addYears(baseDate, 1))

               | EQUAL   => 0

               | GREATER => ~1

        end;

 

    (* return the current birth date                                         *)

    fun getCurrentBirthdate(birthdate : WayDate, current : WayDate) : WayDate =

        create(getMonth(birthdate), getDay(birthdate), getYear(current));

 

    (* return the date closest to the target date                            *)

    fun selectClosestDate(date1 : WayDate, date2 : WayDate, date3 : WayDate,

        target : WayDate) : WayDate =

        let

            fun absDiff(later : WayDate, earlier : WayDate) : int =

                abs(difference(later, earlier));

            val diff1 = absDiff(date1, target);

            val diff2 = absDiff(date2, target);

            val diff3 = absDiff(date3, target)

        in

            if      diff1 <= diff2 andalso diff1 <= diff3 then date1

            else if diff2 <= diff3                        then date2

            else                                               date3

        end;

 

    (* return the birthdate nearest to the current date                      *)

    fun getNearestBirthdate(current : WayDate, birthdate : WayDate) : WayDate =

        let

            val currentBirthdate = getCurrentBirthdate(birthdate, current);

            val prevBirthdate    = addYears(currentBirthdate, ~1);

            val nextBirthdate    = addYears(currentBirthdate,  1)

        in

            selectClosestDate(prevBirthdate, currentBirthdate, nextBirthdate, current)

        end;

 

    (* return the age nearest birthday                                       *)

    fun ageNearestBirthday(current : WayDate, birthdate : WayDate) : int =

        let

            val nearestBirthdate = getNearestBirthdate(current, birthdate)

        in

            age(nearestBirthdate, birthdate)

        end;

 

    (* Return true if a date is the anniversary of the effective date        *)

    fun isAnniversary(date : WayDate, effectiveDate : WayDate) : bool =

        getDay(date)   = getDay(effectiveDate) 

        andalso

        getMonth(date) = getMonth(effectiveDate);

        

    (* Return the greatest anniversary date less than or equal to the current*)

    (*    date                                                               *)

    fun getLastAnniversary(current : WayDate, effective : WayDate) : WayDate =

        let

            val years = diffYears(current, effective)

        in

            addYears(effective, years)

        end;

        

    (* Return true if a date is a monthaversary based on the base date       *)

    fun isMonthaversary(date : WayDate, baseDate : WayDate) : bool =

        getDay(date) = getDay(baseDate);

        

    (* Return the last monthaversary less than or equal a date given an      *)

    (* initial date                                                          *)

    fun getLastMonthaversary(current : WayDate, initial : WayDate) : WayDate =

        let

            val months = diffMonths(current, initial)

        in

            addMonths(initial, months)

        end;

 

 

end (* INSUREDATE *)