Accrual Scripting Examples - Carryovers and Expirations

Carryover Amounts

If the accrual policy allows for carryover, but only up to a certain amount, you use a script like the following.
  • This script would go in the AccrueUp bottom box, before the accrual policy scripts
  • The accrual policy scripts (accrueup scripts) must have a Accrual Max that allows for the carryover
  • The accrueup scripts cannot have an expiration date set
Script Case:
Employees accrue once per year on the 1st of the year. They are allowed to carryover up to 40 hours to the next year.

if( = 1 and reportingdate.month = 1){
   if(getbalance("PTO") > 40){
       $diff = getbalance("PTO") - 40;
      accruedown("PTO", $diff);}

This script will need to run before the script that adds to the employee's balance, so it is important the script is placed before your AccrueUp scripts.

getbalance is used to check the balance of PTO. If it is:
  • over 40 (which is in excess of the carryover amount), then 40 is subtracted from the balance and put in the variable $diff. Then, the accruedown script reduces the PTO balance by the amount of $diff.‚Äč The remaining 40 hours will stay in their bucket and have new PTO added when the accrueup script runs.
  • under or equal to 40, the script, in fact, does nothing. As long as the accrual max on the employee's accrue up account is high enough to allow for the carryover and there is no expiration date set on the hours, the remaining PTO will stay on their balance and their new year accrual will add that into their balance.

Carryover Amounts with Expiration Date

While the accrueup script does have an option to set an expiration date for a balance, (it's the last or 5th argument in the accrueup script), it is not possible to set a separate expiration for a carryover amount in the same accrual bucket. This is because the accruals withdraw from the bucket in a "last in - first out" method. In other words, an expiration date won't take into account if an employee has used any of their carryover amount.

There is, however, another way to handle a carryover specific expiration date which is addressed in Accrual Carryover - Setting an Expiration Specific to the Carryover.

We also can script a reduction to the employee's overall balance on a specific date. If the balance is over their designated annual accrual amount, then the script will reduce their bucket by the excess.

To illustrate with an example:
  • Employees are allowed to carryover up to 40 hours into the new accrual year
  • They must use their carryover amount them by April 30 or they expire.
  • Sarah carries over 40 hours on January 1st.
  • She also normally earns 80 hours of PTO per year on January 1st, so on January 1st, she has a total of 120 PTO hours.
  • Sarah uses 24 hours of PTO between January 1st and April 30th.
  • A script needs to deduct 16 hours from her PTO balance on May1st because she did not use all her carryover by April 30th.
This script will run on May 1st and check the employee's balance. If it is over 80, it will reduce the balance to 80.

if( = dateserial(reportingdate.year, 5, 1) and getbalance("PTO") > 80){
   $carryoverDiff = getbalance("PTO") - 80;
   accruedown("PTO", $carryoverDiff);

The dateserial function is used to create the date that is May 1st of the current year, which is compared to the current date ( If the date is May 1st, it will also use the getbalance function to check if the balance is over 80.

If both of those conditions are true, a variable called $carryoverDiff is created that stores the overage amount and the accruedown script is used to reduce the employees PTO by that amount.

Since an employees annual accrual amount varies by tenure, you could also add a condition that checks how many months of service the employee has on May 1st and use a different annual max based on that value.

Expiring Accruals on an Anniversary Date

This script added to a clients accruals allows employees earned accruals to expire on their anniversary. Meaning they will accrue time starting on their anniversary but any unused accrued time will then expire again in a years time from that date.

An example of the script creating the expiration date itself looks like this:


$expDate = dateserial(reportingdate.year + 1, month(employee.startdate), day(employee.startdate));


In this example, $expDate is a variable that holds the date of the expiration.

The dateserial function creates a date out of the current year plus 1, the month of the employee's start date and the day of the employee start date. Once we know that date, we can compare it to to see if the day on which the script is running, is in fact, the employee's anniversary date.

This case introduces you to how we can determine dates that are employee specific. However, in most cases, an expiration date would be the day before the employee's anniversary date. The following section will explain how to make that modification.

Expiring Accruals on the Day Before an Anniversary Date

Once we can determine the employee's next anniversary date using the example above, determining the day before that date is as simple as subtracting one day

$expDate = dateserial(reportingdate.year + 1, month(employee.startdate), day(employee.startdate)) - 1;

As you can see, the above script line looks identical except for the "-1" that follows the dateserial function. So we are essentially saying, "After you have constructed the next employee anniversary date, subtract 1 day from that date.

What if the expiration date is in the current year?
The above script could work fine for a once per year accrual, but if an employee accrues per month or per pay period, then the expiration date might be in the current year. For instance, if an employee's hire date is March 15th and they accrue per pay period, then accruals for the months of January, February and part of March would expire on March 14th of the current year. So to address that, we
  • set the expiration date to the day before the employee's start date in the current year
  • add a logic test to see if the current date after the expiration date, if so we can adjust accordingly

$expdate = dateserial(reportingdate.year, month(employee.startdate), day(employee.startdate)) - 1;
if( > $expdate){
    $expdate = dateserial(reportingdate.year + 1, month(employee.startdate), day(employee.startdate)) - 1;}

If a policy accrues on an employee's date of hire and the hours need to expire one year from that date, but the day before, you can use the following script to set that expiration in the accrueup script.

Script Case
  • Employees accrue on the last day of each pay period
  • The accrual year is based on the employee's start date
  • Any balance earned during the accrual year must be used by the day before the next occurrence of their start date
$expdate = dateserial(reportingdate.year, month(employee.startdate), day(employee.startdate)) - 1;
if( > $expdate){
    $expdate = dateserial(reportingdate.year + 1, month(employee.startdate), day(employee.startdate)) - 1;
accrueup("Personal", 3.333, 80, "", $expdate);

First a variable ($expdate) is setup to determine the expiration date. The dateserial function will create a date which is equivalent to the day before the employee's anniversary for the current year. However, the second line will determine if the current date is after the employee's anniversary date for the current year. If it is, it will change $expdate to one year from that date.

Once we have $expdate set correctly, we add that as the 5th argument to the accrueup script which sets the expiration for that instance of the accrual.

Accrue on Anniversary Date and 6 Months After Anniversary Date

This script could be used in instances where an employee gets their Vacation amount split up into two segments over the course of the year. 

$ann = dateadd("y", cint(employee.yearsofservice), employee.startdate);
$sixmonth = dateadd("mm", ((cint(employee.yearsofservice) * 12) + 6), employee.startdate);

if( >= "2014-01-01" and ( = $ann or = $sixmonth)){
   if(employee.monthsofservice >= 0){
       accrueup("Vacation", (40 / 2), 40, (employee.startdate) + 90);

The first line of the script determines the annual anniversary date, even for employees that have just been hired. It does this by using the cint function to get a whole number of the employee's years of service. Then, the dateadd function adds that value to the years portion of the employee's startdate.

The second line determines the 6 month mark. It does this by once again using the cint function to determine a whole number of years of service. Then that is converted to months by multiplying by 12. After we add 6 more months to that, the dateadd function now adds that, in months, to the employee's start date to get their 6 month mark.

After the two dates are set as variables, the script checks to see if the current date is after Jan. 1 of 2014 (the start date of the accruals) and either the employees anniversary date or their bi-annual anniversary date. If those conditions are true, the script will begin checking months of service and accrue hours accordingly.

Expiring Accruals on the Last Day of a Pay Period that Contains Dec. 31

If a policy accrues per pay period and also expires balances at the end of the year on the last day of the last pay period of the year (so, instead of expiring exactly on December 31st, it could expire before or after that date, depending on when the pay period ends) this script will determine that date.

This script assumes a bi-weekly pay period. 

It would go in the accrueup bottom script box.

$eoy = dateserial(reportingdate.year,12,31) -;
$eop = reportingdate.payperiodend -;
$eopaeoy=( (14- (($eoy - $eop)%14)) + $eoy );

if( = reportingdate.payperiodend){
    accrueup("PTO", 8,"","",dateadd("d", $eopaeoy,

The math used to determine the exact date of expiration is rather complex. The first three lines are determining how many days until the last day of the last pay period of the year. Then, in the accrueup script, the dateadd function will add the number of days to the current date as the expiration date.

Did you find this article helpful?