<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: PTODesk</title>
    <description>The latest articles on DEV Community by PTODesk (@ptodesk).</description>
    <link>https://dev.to/ptodesk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4138332%2F1fcdfe24-9eee-40f1-9125-d63407e89cdc.png</url>
      <title>DEV Community: PTODesk</title>
      <link>https://dev.to/ptodesk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ptodesk"/>
    <language>en</language>
    <item>
      <title>PTO accrual is date math, not a spreadsheet column: four things that break</title>
      <dc:creator>PTODesk</dc:creator>
      <pubDate>Tue, 22 Sep 2026 21:45:11 +0000</pubDate>
      <link>https://dev.to/ptodesk/pto-accrual-is-date-math-not-a-spreadsheet-column-four-things-that-break-2mm6</link>
      <guid>https://dev.to/ptodesk/pto-accrual-is-date-math-not-a-spreadsheet-column-four-things-that-break-2mm6</guid>
      <description>&lt;p&gt;Most small teams track paid time off in a shared spreadsheet. It works right up until it doesn't, and the failures are always the same four. I have spent the last while building a leave tracker, so here is what I learned about the math.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. A balance should be a sum, not a cell
&lt;/h2&gt;

&lt;p&gt;If the balance lives in a cell, you can never answer "why do I have 12.5 days?". Store every event instead — opening balance, each accrual, each booking, each adjustment — and derive the balance as a sum of the ledger. It costs you a join and buys you an audit trail plus the ability to show an employee the arithmetic instead of asking them to trust it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;opening   +10.96
accrual   + 0.63   (pay period 17)
usage     - 1.00
--------------------
available   10.59
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Accrued, available and projected are three different numbers
&lt;/h2&gt;

&lt;p&gt;Employees read one number and assume it is theirs. It usually isn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;accrued&lt;/strong&gt; — what the ledger says has been earned to date&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;available&lt;/strong&gt; — accrued minus days already booked but not yet taken&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;projected&lt;/strong&gt; — accrued plus what will accrue by a future date&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A request in June for two weeks at Christmas is valid against &lt;em&gt;projected&lt;/em&gt;, not against &lt;em&gt;available&lt;/em&gt;. Systems that only model &lt;em&gt;available&lt;/em&gt; force managers back into a side calendar, which defeats the point of tracking at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Mid-year proration is a real formula, and it is easy to get wrong
&lt;/h2&gt;

&lt;p&gt;Hire someone on 15 June on a 20-day policy and they do not get 20 days, and they do not get 10 either. Over a calendar year:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;20 × 200 / 365 = 10.96 days
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;200 being the days remaining in the year from the hire date. Rounding this to "half the year, so half the entitlement" is the single most common spreadsheet bug I have seen, and it compounds because next year's carryover is computed from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. US state sick leave does not use one denominator
&lt;/h2&gt;

&lt;p&gt;If you are building for US teams: seventeen states and DC mandate paid sick leave accrual, and they do not agree on the rate.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rate&lt;/th&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 hr / 30 worked&lt;/td&gt;
&lt;td&gt;14 states&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 hr / 35 worked&lt;/td&gt;
&lt;td&gt;Rhode Island&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 hr / 37 worked&lt;/td&gt;
&lt;td&gt;DC (varies by employer size)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 hr / 40 worked&lt;/td&gt;
&lt;td&gt;Washington&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 hr / 52 worked&lt;/td&gt;
&lt;td&gt;Vermont&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Caps differ too — Minnesota and Washington have no annual cap at all. The practical lesson is that the rule cannot be a constant in your code. It needs an effective date and a citation, so that when a legislature changes something you can see what changed, when, and which balances were computed under the old rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;If you are writing this yourself: model the ledger first, keep the three balance types distinct, prorate on days rather than months, and version your jurisdiction rules by effective date. If you would rather not write it, this is what I build at &lt;a href="https://ptodesk.com" rel="noopener noreferrer"&gt;PTODesk&lt;/a&gt; — happy to answer questions about any of the above in the comments.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>database</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
