Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Calculate your income in The Netherlands with and without a 30% ruling.
# To check if this is up-to-date with the tax rates go to
# http://www.expatax.nl/tax-rates-2015.php and see if there's anything
# newer there.
#
# I make no guarantees that any of this is correct. I calculated this
# at the time and have been updating it when new tax rates come along
# because people keep finding this useful.
#
# There's also an interactive JS version of this created by
# @stevermeister at
# https://github.com/stevermeister/dutch-tax-income-calculator
# although the two seem to show conflicting values and I have no idea
# which one is correct...
use strict;
use warnings;
use Text::TabularDisplay;
use List::Util qw(sum);
my $start = 30_000 || $ARGV[0];
my $end = 100_000 || $ARGV[1];
my $step = 1_000 || $ARGV[2];
my @data;
for ( my $salary = $start ; $salary <= $end ; $salary += $step ) {
push @data => [
# Your Gross income
eurofy($salary),
# Without 30% ruling
eurofy( $salary - taxes_for($salary) ),
percentify( taxes_for($salary), $salary ),
# With 30% ruling
eurofy( $salary - taxes_for( $salary * .7 ) ),
percentify( taxes_for( $salary * .7 ), $salary ),
];
}
my $table = Text::TabularDisplay->new(
"Gross income\n(before taxes)",
"Net income\n(after taxes)",
"Tax rate",
"Net income\n(after taxes,\nwith 30% ruling)",
"Tax rate",
);
$table->add(@$_) for @data;
print $table->render, "\n";
exit;
sub taxes_for {
my $income = shift;
my @tax_brackets = (
# difference tax rate
[ 19_822 => .3650 ],
[ 57_585 - 19_822 => .42 ],
[ 0 => .52 ],
);
my $money_left = $income;
my $taxes = 0;
foreach my $bracket (@tax_brackets) {
my ( $progressive_amount, $taxes_for ) = @$bracket;
my $taxable_amount = $money_left;
if ( $taxable_amount > $progressive_amount ) {
$taxable_amount = $progressive_amount if $progressive_amount;
}
$money_left -= $taxable_amount;
$taxes += $taxable_amount * $taxes_for;
last unless $money_left;
}
return $taxes;
}
# From perlfaq5
sub commify {
local $_ = shift;
1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
return $_;
}
sub percentify {
my ( $amount, $total ) = @_;
return sprintf "%.1f%%" => ( ( 100 * $amount ) / $total );
}
sub eurofy {
my ($number) = @_;
# Round it
$number = int $number;
return sprintf( "%s EUR", commify($number) );
}
__DATA__
$ perl 30-income-calculon.pl
+----------------+---------------+----------+------------------+----------+
| Gross income | Net income | Tax rate | Net income | Tax rate |
| (before taxes) | (after taxes) | | (after taxes, | |
| | | | with 30% ruling) | |
+----------------+---------------+----------+------------------+----------+
| 30,000 EUR | 18,490 EUR | 38.4% | 22,270 EUR | 25.8% |
| 31,000 EUR | 19,070 EUR | 38.5% | 22,976 EUR | 25.9% |
| 32,000 EUR | 19,650 EUR | 38.6% | 23,682 EUR | 26.0% |
| 33,000 EUR | 20,230 EUR | 38.7% | 24,388 EUR | 26.1% |
| 34,000 EUR | 20,810 EUR | 38.8% | 25,094 EUR | 26.2% |
| 35,000 EUR | 21,390 EUR | 38.9% | 25,800 EUR | 26.3% |
| 36,000 EUR | 21,970 EUR | 39.0% | 26,506 EUR | 26.4% |
| 37,000 EUR | 22,550 EUR | 39.1% | 27,212 EUR | 26.5% |
| 38,000 EUR | 23,130 EUR | 39.1% | 27,918 EUR | 26.5% |
| 39,000 EUR | 23,710 EUR | 39.2% | 28,624 EUR | 26.6% |
| 40,000 EUR | 24,290 EUR | 39.3% | 29,330 EUR | 26.7% |
| 41,000 EUR | 24,870 EUR | 39.3% | 30,036 EUR | 26.7% |
| 42,000 EUR | 25,450 EUR | 39.4% | 30,742 EUR | 26.8% |
| 43,000 EUR | 26,030 EUR | 39.5% | 31,448 EUR | 26.9% |
| 44,000 EUR | 26,610 EUR | 39.5% | 32,154 EUR | 26.9% |
| 45,000 EUR | 27,190 EUR | 39.6% | 32,860 EUR | 27.0% |
| 46,000 EUR | 27,770 EUR | 39.6% | 33,566 EUR | 27.0% |
| 47,000 EUR | 28,350 EUR | 39.7% | 34,272 EUR | 27.1% |
| 48,000 EUR | 28,930 EUR | 39.7% | 34,978 EUR | 27.1% |
| 49,000 EUR | 29,510 EUR | 39.8% | 35,684 EUR | 27.2% |
| 50,000 EUR | 30,090 EUR | 39.8% | 36,390 EUR | 27.2% |
| 51,000 EUR | 30,670 EUR | 39.9% | 37,096 EUR | 27.3% |
| 52,000 EUR | 31,250 EUR | 39.9% | 37,802 EUR | 27.3% |
| 53,000 EUR | 31,830 EUR | 39.9% | 38,508 EUR | 27.3% |
| 54,000 EUR | 32,410 EUR | 40.0% | 39,214 EUR | 27.4% |
| 55,000 EUR | 32,990 EUR | 40.0% | 39,920 EUR | 27.4% |
| 56,000 EUR | 33,570 EUR | 40.1% | 40,626 EUR | 27.5% |
| 57,000 EUR | 34,150 EUR | 40.1% | 41,332 EUR | 27.5% |
| 58,000 EUR | 34,688 EUR | 40.2% | 42,038 EUR | 27.5% |
| 59,000 EUR | 35,168 EUR | 40.4% | 42,744 EUR | 27.6% |
| 60,000 EUR | 35,648 EUR | 40.6% | 43,450 EUR | 27.6% |
| 61,000 EUR | 36,128 EUR | 40.8% | 44,156 EUR | 27.6% |
| 62,000 EUR | 36,608 EUR | 41.0% | 44,862 EUR | 27.6% |
| 63,000 EUR | 37,088 EUR | 41.1% | 45,568 EUR | 27.7% |
| 64,000 EUR | 37,568 EUR | 41.3% | 46,274 EUR | 27.7% |
| 65,000 EUR | 38,048 EUR | 41.5% | 46,980 EUR | 27.7% |
| 66,000 EUR | 38,528 EUR | 41.6% | 47,686 EUR | 27.7% |
| 67,000 EUR | 39,008 EUR | 41.8% | 48,392 EUR | 27.8% |
| 68,000 EUR | 39,488 EUR | 41.9% | 49,098 EUR | 27.8% |
| 69,000 EUR | 39,968 EUR | 42.1% | 49,804 EUR | 27.8% |
| 70,000 EUR | 40,448 EUR | 42.2% | 50,510 EUR | 27.8% |
| 71,000 EUR | 40,928 EUR | 42.4% | 51,216 EUR | 27.9% |
| 72,000 EUR | 41,408 EUR | 42.5% | 51,922 EUR | 27.9% |
| 73,000 EUR | 41,888 EUR | 42.6% | 52,628 EUR | 27.9% |
| 74,000 EUR | 42,368 EUR | 42.7% | 53,334 EUR | 27.9% |
| 75,000 EUR | 42,848 EUR | 42.9% | 54,040 EUR | 27.9% |
| 76,000 EUR | 43,328 EUR | 43.0% | 54,746 EUR | 28.0% |
| 77,000 EUR | 43,808 EUR | 43.1% | 55,452 EUR | 28.0% |
| 78,000 EUR | 44,288 EUR | 43.2% | 56,158 EUR | 28.0% |
| 79,000 EUR | 44,768 EUR | 43.3% | 56,864 EUR | 28.0% |
| 80,000 EUR | 45,248 EUR | 43.4% | 57,570 EUR | 28.0% |
| 81,000 EUR | 45,728 EUR | 43.5% | 58,276 EUR | 28.1% |
| 82,000 EUR | 46,208 EUR | 43.6% | 58,982 EUR | 28.1% |
| 83,000 EUR | 46,688 EUR | 43.7% | 59,636 EUR | 28.1% |
| 84,000 EUR | 47,168 EUR | 43.8% | 60,272 EUR | 28.2% |
| 85,000 EUR | 47,648 EUR | 43.9% | 60,908 EUR | 28.3% |
| 86,000 EUR | 48,128 EUR | 44.0% | 61,544 EUR | 28.4% |
| 87,000 EUR | 48,608 EUR | 44.1% | 62,180 EUR | 28.5% |
| 88,000 EUR | 49,088 EUR | 44.2% | 62,816 EUR | 28.6% |
| 89,000 EUR | 49,568 EUR | 44.3% | 63,452 EUR | 28.7% |
| 90,000 EUR | 50,048 EUR | 44.4% | 64,088 EUR | 28.8% |
| 91,000 EUR | 50,528 EUR | 44.5% | 64,724 EUR | 28.9% |
| 92,000 EUR | 51,008 EUR | 44.6% | 65,360 EUR | 29.0% |
| 93,000 EUR | 51,488 EUR | 44.6% | 65,996 EUR | 29.0% |
| 94,000 EUR | 51,968 EUR | 44.7% | 66,632 EUR | 29.1% |
| 95,000 EUR | 52,448 EUR | 44.8% | 67,268 EUR | 29.2% |
| 96,000 EUR | 52,928 EUR | 44.9% | 67,904 EUR | 29.3% |
| 97,000 EUR | 53,408 EUR | 44.9% | 68,540 EUR | 29.3% |
| 98,000 EUR | 53,888 EUR | 45.0% | 69,176 EUR | 29.4% |
| 99,000 EUR | 54,368 EUR | 45.1% | 69,812 EUR | 29.5% |
| 100,000 EUR | 54,848 EUR | 45.2% | 70,448 EUR | 29.6% |
+----------------+---------------+----------+------------------+----------+
@maxadamo

LOL +1 :)

@Grindizer

Hello, i don't understand why tax rate is 0.2 for the 2nd bracket (33_363 - 19_645). From your link (http://www.expatax.nl/tax_rates_2013.php#.UfZlcBddUnY) I though it should be 0.42 ?

@davydovmax

Grindizer, you seem to be right, there should be 0.42, which is 10.85% (income tax) plus 31.15% (Premium National Insurance).

@kovpas

Fixed a problem with 2nd bracket: https://gist.github.com/kovpas/6182246

@dncnmckn

Very useful. Thank you.

@konstantin-gorbunov

it should be updated, brackets was changed

@DeclanWatson

this is incorrect, to my understanding it is only the additional salary that you earn over the threshold that benefits from 30% ruling. Or am i wrong?

@stevermeister

converted to JavaScript and made online tax calculator http://stepansuvorov.com/useIt/dit/

@samacumen

Somehow I feel the JavaScript and made online tax calculator is not completely correct.
If one enters the gross say as 18000, it still shows 37% tax (full) and 25.2% tax (with 30% ruling). This is not the case, I believe and is tax slab based below 19,000 euros.

Please correct me if I am wrong.

@avar
Owner

Sorry guys, hadn't updated this in a while. I fixed that bug with the wrong tax percentages, and updated it for the 2014 tax changes. It should be correct now.

@dzhibas

+1 thanks!

@shekhardesigner

Damn useful. Thanks a lot!!

@MikelArnaiz

2015 rates:
0 - 19,822: 36.5%
19,822 - 33,589: 42%
33,589 - 57,585: 42%
From 57,585: 52%

@Mollan86

Hi! I do not understand your calculations. For a gross salary of 37.000, the actual net income (2015) is around 300€ lower than the real net income. Do some categories have special rates and/or other tax discounts?
This is also confirmed by this website, which calculations are closer to the real net income: http://www.expatax.nl/calculations/grosstonet/gross-net.htm

@chrisjbrown

Also agree with @Mollan86. Net income is far great than my real net income.

@avar
Owner

Thanks. I've updated this just now for the 2015 rates. Sorry about the delay everyone, just noticed when someone linked to this and I saw it was still using 2014, and this whole discussion that I'd missed.

@avar
Owner

@stevermeister: I added a link to yours at the top. Also our two versions show different values, yours allows you to calculate with accounting for age & social security. But the values are always slightly different, do you know what mistake I've made here?

This table was never meant to be your fully tax story, just an approximation to show how much of a difference the 30% ruling made. But I think at the time I wrote it it was accurate for that assuming a spherical cow in a vacuum...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.