DEV Community

levent çelik
levent çelik

Posted on

Reading my own paycheck: turning gross salary into hourly rate in JavaScript

I switched companies last year and the offer letter quoted my salary as an annual gross number. The recruiter was confident, the email looked clean, and yet I still wanted to know one thing my brain refuses to compute on the fly: "how much per hour is that, really?"

I ended up writing a tiny script to do it for me, and then kept extending it until I had a small toolkit for reasoning about my own pay. Sharing the bits I now keep in a paycheck.ts file in case anyone else finds it useful.

The naive conversion

The number every salary site quotes is annual gross divided by 2,080. Forty hours times fifty-two weeks. As code:

function grossHourly(annual) {
  return annual / 2080;
}

grossHourly(95000); // 45.67
Enter fullscreen mode Exit fullscreen mode

Fine for a back-of-the-envelope. But anyone who has actually filled out a timesheet knows that 2,080 is a fiction. You probably take vacation, you have public holidays, and you almost certainly do not bill for sick days.

The slightly less wrong conversion

Adjust for paid time off and holidays:

function effectiveHourly({ annual, weeksOff = 4, holidays = 10 }) {
  const workingHours = (52 - weeksOff) * 40 - holidays * 8;
  return annual / workingHours;
}

effectiveHourly({ annual: 95000, weeksOff: 4, holidays: 10 });
// 51.42
Enter fullscreen mode Exit fullscreen mode

Four weeks of vacation and ten holidays moves $95k from $45.67/hr to $51.42/hr. That difference (almost six dollars an hour) is the part that recruiters silently round away when they pitch annual numbers.

This is exactly the calculation behind the Salary to Hourly Calculator on Equation Solver, which is the page I send to anyone comparing W2 to contract offers. Plug in both, adjust the assumptions, and the apples-to-apples comparison stops feeling like a guess.

Going the other way: contract to salary equivalent

The inverse is just as useful. If you are a contractor quoting an hourly rate, what "salary" should that feel like to a friend on payroll? You usually want to undercount, not overcount, so include their benefits as a percentage of base pay:

function salaryEquivalent({ hourly, weeksOff = 4, holidays = 10, benefitsPct = 0.25 }) {
  const workingHours = (52 - weeksOff) * 40 - holidays * 8;
  const base = hourly * workingHours;
  return base * (1 - benefitsPct);
}

salaryEquivalent({ hourly: 75 });
// 103950
Enter fullscreen mode Exit fullscreen mode

That 25% benefits haircut covers things like health insurance, retirement match, and the unpaid time you take when you are sick. The number is approximate but it stops contractors from cheerfully comparing $75/hr to a $156k salary and feeling like they won.

For more careful gross-pay reasoning, including bi-weekly and semi-monthly views, the Salary Calculator on Equation Solver does the splits cleanly. I find it easier to use than building a spreadsheet from scratch.

The auto loan that changed how I budget

The last script in the toolkit is for the recurring side of the same conversation: monthly costs you have already committed to. The biggest one for most working adults, after rent or mortgage, is a car.

function autoPayment({ price, downPayment, annualRate, years }) {
  const principal = price - downPayment;
  const r = annualRate / 12;
  const n = years * 12;
  return (principal * r) / (1 - Math.pow(1 + r, -n));
}

autoPayment({
  price: 32000,
  downPayment: 4000,
  annualRate: 0.07,
  years: 6,
}); // 477.69
Enter fullscreen mode Exit fullscreen mode

My own mistake here was doing this math too late. I signed for the car first, then ran the numbers, then realized that the difference between a 5-year and 7-year loan was something like $40 a month but also $3,000+ in extra interest. Ouch.

The Auto Loan Calculator on Equation Solver shows the total interest you pay over the life of the loan, which is the number my younger self should have been looking at, not just the monthly payment.

Why bother coding any of this

Fair question. Calculators exist. Spreadsheets exist. The reason I write these as functions is muscle memory: when I see an offer, a quote, a payment plan, I can plug numbers in faster than I can open a tab. The math is dead simple, the value is almost entirely psychological. Once you have built the mental model in code, you start spotting bad deals from the page they are written on.

If you are mentoring junior engineers, this is also a fun first "real-world utility" project. They will use it, their friends will ask them about it, and somewhere along the way they will internalize that JavaScript is a perfectly reasonable place to do arithmetic that matters.

Top comments (0)