Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@troelskn
Last active November 22, 2023 17:12
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save troelskn/c00e0035139795409976df1c7f0026eb to your computer and use it in GitHub Desktop.
Save troelskn/c00e0035139795409976df1c7f0026eb to your computer and use it in GitHub Desktop.
Danish tax calculations for Google sheets
function DK_TAX_PARSE_OPTIONS(opts) {
var options = {
hasChildren: true, // Do you receive "børnepenge"?
isFamily: true, // Are you married (and your spouse without income)?
interests: 44256, // Deductible interests paid (typically on a mortgage)
churchTax: 0.00867, // Set your church tax rate here, if you are a member of the church. Otherwise set to 0.0
municipalityTaxRate: 0.24926 // Find you tax rate here: https://www.skm.dk/skattetal/satser/kommuneskatter
};
var applyOption = function(key, value) {
var key = key.trim();
if (typeof value == "string") {
var value = value.trim();
if (key == "hasChildren" || key == "isFamily") {
options[key] = value.toLowerCase() == "true";
} else if (key == "churchTax" || key == "municipalityTaxRate") {
options[key] = parseFloat(value);
} else {
options[key] = parseInt(value);
}
} else {
options[key] = value;
}
};
if (opts) {
if (typeof opts.forEach != "undefined") {
opts.forEach(function(row) {
applyOption(row[0], row[1]);
});
} else {
opts.split(";").forEach(function(pair) {
var tmp = pair.split("=");
applyOption(tmp[0], tmp[1]);
});
}
}
return options;
}
/**
* Calculate the remainder after PI taxes.
* + gross The gross income
* + grossOffset Previously taxed gross amount
*
* Antagelser (2019)
*
* AM bidrag (bruttoskat) 8%
* Personfradrag 2 x 46.200
* Bundskat 12,16%
* Topskat over 513.400 15%
* Kommuneskat 24,926%
* Børnepenge over 782.600 2%
* Kirkeskat 0,867%
*/
function DK_TAX_PERSONAL_INCOME(gross, grossOffset, options) {
var kommuneskat, bundskat, topskat, topskat_limit, toptopskat, toptopskat_limit, labour_deductions, deduction_limit, taxable, toptopskat_taxable, topskat_taxable, bundskat_taxable, net, netOffset;
options = DK_TAX_PARSE_OPTIONS(options);
if (typeof(grossOffset) == "number") {
netOffset = DK_TAX_PERSONAL_INCOME(grossOffset);
} else {
grossOffset = 0;
netOffset = 0;
}
gross += grossOffset;
kommuneskat = options.municipalityTaxRate;
bundskat = kommuneskat + 0.1213 + options.churchTax;
topskat = Math.min(bundskat + 0.155, 0.5205);
topskat_limit = 513400;
toptopskat = topskat + 0.02;
toptopskat_limit = options.hasChildren ? 782600 : 100000000;
labour_deductions = 37200 + 2100; // Andre fradrag: Beskæftigelse, Job
deduction_limit = 46200 * (options.isFamily ? 2 : 1); // Personfradrag
deduction_limit += options.interests * 0.336; // Fradrag for renter på lån
deduction_limit += labour_deductions * 0.249;
taxable = gross * 0.92;
if (taxable <= deduction_limit) {
return Math.round(taxable - netOffset);
}
taxable -= deduction_limit;
toptopskat_taxable = Math.max(0, taxable - toptopskat_limit);
topskat_taxable = Math.min(Math.max(0, taxable - topskat_limit), toptopskat_limit - topskat_limit);
bundskat_taxable = taxable - (topskat_taxable + toptopskat_taxable);
net = deduction_limit;
net += bundskat_taxable * (1.0 - bundskat);
net += topskat_taxable * (1.0 - topskat);
net += toptopskat_taxable * (1.0 - toptopskat);
return Math.round(net - netOffset);
}
/**
* Calculate the remainder after business taxes.
* + gross The gross income
*/
function DK_TAX_BUSINESS(gross) {
return Math.round(gross * (1 - 0.22));
}
/**
* Calculate the remainder after PAL tax on ratepension gains.
* + gross The gross gains
*/
function DK_TAX_RATEPENSION(gross) {
return Math.round(gross * (1 - 0.153));
}
/**
* Calculate the remainder tax on stock gains.
* + gross The gross gains
*/
function DK_TAX_STOCK(gross, options) {
var limit, high, low;
options = DK_TAX_PARSE_OPTIONS(options);
limit = 54000 * (options.isFamily ? 2 : 1);
high = Math.max(0, gross - limit);
low = gross - high;
return Math.round((low * (1 - 0.27)) + (high * (1 - 0.42)));
}
/**
* Find the gross required to provide a given net
*/
function DK_TAX_PERSONAL_INCOME_REVERSE(net) {
var result, gross, increment;
increment = 10000;
gross = increment;
while (true) {
result = DK_TAX_PERSONAL_INCOME(gross);
if (result >= net) {
return gross;
}
gross += increment;
}
}
/**
* Find the gross required to provide a given net
*/
function DK_TAX_STOCK_REVERSE(net, options) {
var limit, net_limit, high, low;
options = DK_TAX_PARSE_OPTIONS(options);
limit = 54000 * (options.isFamily ? 2 : 1);
net_limit = limit * (1 - 0.27);
high = Math.max(0, net - net_limit);
low = net - high;
return Math.round((low / (1 - 0.27)) + (high / (1 - 0.42)));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment