Federal Income

Payroll::US::FedIncome
calculate(
gross - total amount of pay
date - date to be paid on. affects tax rates format YYYYMMDD
method - the method to use for calculation (currently only percentage )
allowances - federal allowances
period - annual, semiannual, quarterly, monthly, semimonthly, biweekly, weekly, daily
marital - single or married
periodDays - reference to a hash containing ratios for number of days in periods. defaults to undef, hash can be overriden by the user specifying a hash ref to the same structure, different data.
round - yes, no - defaults to yes - or should user sprintf the result. seems that would be more efficient
)
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)