Federal Income

Payroll::US::StateIncome.pm
StateIncome->calculate(
gross, # - gross pay
date, #- date of payment format YYYYMMDD
method, #- specifies mthod to use. currently only 1
allowances #, - state allowances claimed, integer
period, #- annual, semiannual, quarterly, monthly, semimonthly, biweekly, weekly, daily
marital, #- single, married
federal, #- amount of federal tax withheld here
fYTD #- total federal tax withheld yeart to date
)
The data will be stored by date in a hash, so that calculations will use the proper rates.
iterate over sorted keys descending in data hash.
Compare $date to keys.
Stop when $date >= key.
set $foundDate = $key.
If date < all keys, that is an error.

data{$foundDate}-> | {tables} |
ex. data{20010101}-> | {dailyWithholdingAllowance} | = 11.15
| {dailyTableRows}[X] |

The periodDays hash holds the number of days in a period

periodDays-> | {annual} | = 260
| {semiannual} | = 130
| {quarterly} | = 65
| {monthly} | = 21.67
| {semimonthly} | = 10.84
| {biweekly} | = 10
| {weekly} | = 5
| {daily} | = 1

To calculate the withholding allowance
withholdingAllowance = periodDays->{$period} * data->{$foundDate}->{dailyWithholdingAllowance}
modifiedGross = gross - (allowances * withholdingAllowance)
Use modifiedGross value to determine tax bracket and subsequent percentage by looking up in data{$foundDate}->{tables}. Only generate withholding tables as needed. This will allow for caching type functionality and speed optimizations.
How to generate a table.
generate_table ( period, marital, table=>data{$foundDate}->{tables} )
{
@dailyTableRows = $data->{$foundDate}->{$dailyTableRows}
for $row = 0; row < scalar ($dailyTableRows); row++
{
if $row == 0
$base = 0;
else
{
base = $dailyTableRows[row -1]->percent *
($dailyTableRows[row]->top - $dailyTableRows[row -1]->top)
+ $dailyTableRows[row-1]->base
}
$top = $row->{top} * periodDays{period}
$top *= $row->{marriedRatio} if $marital eq "married"
%tempRow = { top => $top,
base => base ,
percent => $row->{percent} } ;
#dont forget to create array single first
push($table->{$period}->{$marital}, \%tempRow)
}
}
The lookuptables are generated from the data stored in the daily table.
There is an array for the rows sorted descending. This allows us to check the greatest case first. No corner cases.

{dailyTableRows} | [$row]-> | {top}
|  | {percent}
|  | {marriedRatio}

generated tables look like this

tables | {$period => | { single => | [
|  |  | {top => , base => , percent => } ,
|  |  | ] ,
|  | married => | [
|  |  | {top => , base => , percent => } ,
|  |  | ]
|  | }, |
| } |  |

these variables will be lookups from the above generated table.
if !tableexists
generate_table(period, marital, table =>)
tax = $base + (( modifiedGross - $top) * $percent)