<?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: Feroz Sheikh</title>
    <description>The latest articles on DEV Community by Feroz Sheikh (@shekh_firoj_6217570f10c6c).</description>
    <link>https://dev.to/shekh_firoj_6217570f10c6c</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%2F4148658%2F55f15a92-469b-4c81-8811-b23424fc4f26.jpg</url>
      <title>DEV Community: Feroz Sheikh</title>
      <link>https://dev.to/shekh_firoj_6217570f10c6c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shekh_firoj_6217570f10c6c"/>
    <language>en</language>
    <item>
      <title>Parsing bank-statement PDFs in the browser: text layer, tables, and a balance check</title>
      <dc:creator>Feroz Sheikh</dc:creator>
      <pubDate>Sun, 04 Oct 2026 05:48:13 +0000</pubDate>
      <link>https://dev.to/shekh_firoj_6217570f10c6c/parsing-bank-statement-pdfs-in-the-browser-text-layer-tables-and-a-balance-check-4823</link>
      <guid>https://dev.to/shekh_firoj_6217570f10c6c/parsing-bank-statement-pdfs-in-the-browser-text-layer-tables-and-a-balance-check-4823</guid>
      <description>&lt;p&gt;Generic "PDF to Excel" converters are great until you feed them a bank statement. Columns drift, page headers repeat mid-table, wrapped descriptions become extra rows, and the closing balance no longer matches the opening balance plus the sum of amounts. That is not a minor formatting bug — it is a wrong ledger.&lt;/p&gt;

&lt;p&gt;I spent a while on this while building a free, browser-only converter for text-layer statements. Here is the practical checklist I wish I had on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Confirm there is a real text layer
&lt;/h2&gt;

&lt;p&gt;Open the PDF and try to select a single transaction line. If you cannot select text, or you get mojibake, you have a scan (or broken font encoding). Ordinary converters will invent numbers. You need OCR in the statement language first, and you should budget time to fix rows by hand.&lt;/p&gt;

&lt;p&gt;If selection works, you have a text PDF. Prefer a &lt;strong&gt;table-aware&lt;/strong&gt; extractor over a full-page "PDF to Word" pass:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Excel (Microsoft 365 on Windows): &lt;strong&gt;Data → Get Data → From File → From PDF&lt;/strong&gt;, then pick the table on each page&lt;/li&gt;
&lt;li&gt;Tabula (open source): draw a box around the transaction table and export CSV&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Prefer the bank export when it exists
&lt;/h2&gt;

&lt;p&gt;Most online banking apps can export CSV or Excel for a date range. That path beats every PDF pipeline. Use the PDF route only when the bank will not give you a spreadsheet (or you only have the PDF the branch emailed).&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Reconcile row by row, not "looks about right"
&lt;/h2&gt;

&lt;p&gt;After extraction, start from the opening balance and walk each row:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;previous_balance ± amount  ==  new_balance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any failure is a split cell, a merged cell, a repeated page header, or a description that wrapped onto a second line. Those four failure modes cover almost every "converted mess" I have seen.&lt;/p&gt;

&lt;p&gt;A small implementation tip in JavaScript: keep amounts as integers of the minor unit (pence/cents) while you walk the ledger, and only format for display at the end. Floating-point drift will otherwise create false mismatches on long statements.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Keep the file on the device
&lt;/h2&gt;

&lt;p&gt;Bank statements are high-sensitivity documents. Uploading them to a random converter is a privacy decision, not just a convenience one. A client-side parser (pdf.js + your own column heuristics) never sends the bytes to a server. Trade-off: large scanned PDFs OCR slowly in the browser, and you will not magically fix a true scan without an OCR engine that supports the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclosure
&lt;/h2&gt;

&lt;p&gt;I built a free browser converter that runs this balance check locally on text PDFs (not scans): &lt;a href="https://opentoolsuite.com/guides/convert-bank-statement-pdf-to-excel/" rel="noopener noreferrer"&gt;opentoolsuite.com/guides/convert-bank-statement-pdf-to-excel&lt;/a&gt;. Use it, or rebuild the same pattern with Tabula + a spreadsheet — the reconciliation step is the part that actually matters.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Versioned construction formulas: how Construclytic shows the math behind every calculator</title>
      <dc:creator>Feroz Sheikh</dc:creator>
      <pubDate>Thu, 01 Oct 2026 06:08:37 +0000</pubDate>
      <link>https://dev.to/shekh_firoj_6217570f10c6c/versioned-construction-formulas-how-construclytic-shows-the-math-behind-every-calculator-1am2</link>
      <guid>https://dev.to/shekh_firoj_6217570f10c6c/versioned-construction-formulas-how-construclytic-shows-the-math-behind-every-calculator-1am2</guid>
      <description>&lt;p&gt;Most construction calculators hide the arithmetic. You type room size, you get a carton count, and you have no idea whether waste was 5% or 15%, whether the coverage came from the carton label, or whether the code will still produce the same number in eighteen months.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://construclytic.com" rel="noopener noreferrer"&gt;Construclytic&lt;/a&gt; to do the opposite: every published calculator carries a &lt;strong&gt;formula ID&lt;/strong&gt;, a &lt;strong&gt;version&lt;/strong&gt;, a &lt;strong&gt;worked example&lt;/strong&gt;, and a visible calculation trail. The arithmetic is deterministic TypeScript — not LLM-generated totals. Here is how that looks in practice, using the laminate flooring calculator as the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formula IDs are product SKUs for math
&lt;/h2&gt;

&lt;p&gt;The laminate calculator publishes &lt;strong&gt;FLOOR-LAMINATE-001&lt;/strong&gt; (currently v1.0.0). That ID shows up on the result card, in the estimate line, and in the formula registry. If a correction ships, the version bumps and the changelog says so.&lt;/p&gt;

&lt;p&gt;The core expression is intentionally boring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cartons = ceil( L × W × (1 + waste) ÷ carton_coverage )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;L × W&lt;/code&gt; is the measured floor area&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;waste&lt;/code&gt; is an explicit input (default for planning; higher for diagonal / complex layouts)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;carton_coverage&lt;/code&gt; is the square footage printed on the carton you chose&lt;/li&gt;
&lt;li&gt;Rounding to whole cartons happens &lt;strong&gt;once, at the end&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the same method a careful estimator uses on paper. Making it a named, versioned formula means a saved quote from October still explains itself next spring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Waste is an input, not a hidden multiplier
&lt;/h2&gt;

&lt;p&gt;Black-box tools often bake in “about 10%” without saying so. FLOOR-LAMINATE-001 keeps waste as a field:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Straight-lay rooms: often ~8–10%&lt;/li&gt;
&lt;li&gt;Diagonal or busy layouts: 12–15%+&lt;/li&gt;
&lt;li&gt;Click-lock and glue-down do &lt;strong&gt;not&lt;/strong&gt; share a silent default — the coverage and allowance stay on the form&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a worked Quora-sized room (12 × 5 ft, 27 ft² cartons, 10% waste):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;area        = 60 ft²
with waste  = 66 ft²
cartons     = ceil(66 / 27) = 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even with 0% waste you still need 3 cartons (60 ÷ 27 = 2.22). The third carton is spare stock for future repairs — and matching lot numbers later is harder than people expect.&lt;/p&gt;

&lt;p&gt;You can try the same inputs live: &lt;a href="https://construclytic.com/calculators/flooring/laminate" rel="noopener noreferrer"&gt;construclytic.com/calculators/flooring/laminate&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What “tested” means (and what it does not)
&lt;/h2&gt;

&lt;p&gt;Each published calculator has automated checks: Imperial/Metric round-trips, finite results on equivalent projects, and known-answer cases for selected formulas. The &lt;a href="https://construclytic.com/how-we-calculate" rel="noopener noreferrer"&gt;how-we-calculate&lt;/a&gt; page and public formula registry record the tested version and date.&lt;/p&gt;

&lt;p&gt;What we do &lt;strong&gt;not&lt;/strong&gt; claim: independent third-party engineering review, mix design, code compliance, or a supplier quote. Construclytic is a planning workspace. Field checks stay with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why transparency matters for estimators
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Auditability.&lt;/strong&gt; A client or GC can see &lt;em&gt;why&lt;/em&gt; you ordered 14 cartons, not 12.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility.&lt;/strong&gt; Same inputs + same formula version → same purchase quantity months later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teaching.&lt;/strong&gt; Juniors learn the takeoff chain instead of trusting a magic number.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diffability.&lt;/strong&gt; When waste defaults or coverage rules change, the version bump is the signal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are building calculators yourself, the pattern transfers outside construction: name the formula, version it, show the trail, keep policy knobs (waste, packaging steps, tax) as inputs, and never let an LLM invent the numeric result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclosure
&lt;/h2&gt;

&lt;p&gt;I built Construclytic. The laminate calculator above is free, needs no account, and shows FLOOR-LAMINATE-001 on the result. Methodology: &lt;a href="https://construclytic.com/how-we-calculate" rel="noopener noreferrer"&gt;construclytic.com/how-we-calculate&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>UK flight delay compensation (UK261) explained — how much you can claim</title>
      <dc:creator>Feroz Sheikh</dc:creator>
      <pubDate>Wed, 30 Sep 2026 06:18:35 +0000</pubDate>
      <link>https://dev.to/shekh_firoj_6217570f10c6c/uk-flight-delay-compensation-uk261-explained-how-much-you-can-claim-2kdc</link>
      <guid>https://dev.to/shekh_firoj_6217570f10c6c/uk-flight-delay-compensation-uk261-explained-how-much-you-can-claim-2kdc</guid>
      <description>&lt;p&gt;If your flight arrived hours late, you may be owed a fixed cash amount from the airline, on top of meals and a hotel. In the UK these rules are known as &lt;strong&gt;UK261&lt;/strong&gt;, the version of EU Regulation 261/2004 that the UK kept after Brexit.&lt;/p&gt;

&lt;p&gt;It helps to separate three questions: &lt;strong&gt;Is my flight covered? How late did I arrive? Why was it late?&lt;/strong&gt; This guide answers each one using the Civil Aviation Authority's (CAA) own figures.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Is your flight covered?
&lt;/h2&gt;

&lt;p&gt;According to the CAA, UK261 covers a flight if it is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;departing from a UK airport, on any airline&lt;/strong&gt;, or&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;arriving at a UK airport on a UK or EU airline&lt;/strong&gt;, or&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;arriving at an EU airport on a UK airline.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reverse catches people out: a flight &lt;em&gt;into&lt;/em&gt; the UK on a non-UK, non-EU airline (say, a US carrier from New York) is generally &lt;strong&gt;not&lt;/strong&gt; covered, while the same airline's flight &lt;em&gt;out of&lt;/em&gt; the UK is.&lt;/p&gt;

&lt;p&gt;What matters is the airline that actually &lt;strong&gt;operated&lt;/strong&gt; the flight, not the one that sold you the ticket or appears in a codeshare.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How much: the four CAA amounts
&lt;/h2&gt;

&lt;p&gt;Compensation is a fixed amount. The CAA is explicit that it "is not linked to the price you paid for your ticket." It depends on the flight distance and, for long-haul flights, on how late you arrived:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flight distance&lt;/th&gt;
&lt;th&gt;Example (CAA)&lt;/th&gt;
&lt;th&gt;Arrival delay&lt;/th&gt;
&lt;th&gt;Compensation per person&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Under 1,500 km&lt;/td&gt;
&lt;td&gt;Glasgow–Amsterdam&lt;/td&gt;
&lt;td&gt;3+ hours&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;£220&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,500–3,500 km&lt;/td&gt;
&lt;td&gt;East Midlands–Marrakesh&lt;/td&gt;
&lt;td&gt;3+ hours&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;£350&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Over 3,500 km&lt;/td&gt;
&lt;td&gt;London–New York&lt;/td&gt;
&lt;td&gt;3 to 4 hours&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;£260&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Over 3,500 km&lt;/td&gt;
&lt;td&gt;London–New York&lt;/td&gt;
&lt;td&gt;more than 4 hours&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;£520&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Many tables show only "£220 / £350 / £520" and leave out the £260 row. A long-haul flight arriving 3.5 hours late gets £260, not £520.&lt;/p&gt;

&lt;p&gt;The number that counts is &lt;strong&gt;arrival&lt;/strong&gt; delay, not departure delay. The CAA says compensation may apply "if you arrive more than three hours late at your destination airport."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connecting flights on one booking:&lt;/strong&gt; the CAA measures distance "between the first and last airport in your booking," and only lateness at your final destination counts. Arriving late at the connection point doesn't count on its own. &lt;strong&gt;Separate bookings&lt;/strong&gt; (self-transfer) get no compensation for a missed onward flight, although each flight keeps its own rights.&lt;/p&gt;

&lt;p&gt;To find your band, work out the great-circle distance and apply the table. I built a free &lt;a href="https://flightrefundcalc.com/uk-flight-compensation" rel="noopener noreferrer"&gt;UK flight compensation calculator&lt;/a&gt; that does the distance maths and shows all four CAA bands, but you can check it by hand too.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why was it late? The "extraordinary circumstances" test
&lt;/h2&gt;

&lt;p&gt;Airlines don't have to pay compensation if the delay was caused by &lt;strong&gt;extraordinary circumstances&lt;/strong&gt;, events outside the airline's control. The CAA's examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;weather incompatible with safe operation&lt;/li&gt;
&lt;li&gt;strikes unrelated to the airline (airport staff, ground handlers, air traffic control, Border Force)&lt;/li&gt;
&lt;li&gt;terrorism or sabotage, security risks, political or civil unrest&lt;/li&gt;
&lt;li&gt;hidden manufacturing defects (e.g. a manufacturer recall that grounds a fleet)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ordinary technical faults are generally not extraordinary.&lt;/strong&gt; The CAA points to the &lt;em&gt;Jet2 v Huzar&lt;/em&gt; judgment (Court of Appeal, 2014) and &lt;em&gt;van der Lans v KLM&lt;/em&gt; (European Court, 2015), which found that technical problems, including early failure of a component, are not extraordinary circumstances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A current example:&lt;/strong&gt; after the NATS flight-planning failure on 8 September 2026, the CAA said that delays and cancellations caused by the incident, and its knock-on effects, "are likely to be 'extraordinary circumstances'". Passengers are therefore "unlikely to be entitled to compensation" for those disruptions. The CAA added that airlines must still look after passengers, and that its view is guidance, not a ruling on individual cases. It took the same view of a second NATS technical issue, at the Prestwick centre in Scotland, on 21 September 2026.&lt;/p&gt;

&lt;p&gt;If you're unsure, claim anyway. The CAA says the airline "should explain to you the reason for the disruption" and, if it relies on extraordinary circumstances, "will need to clearly set out why."&lt;/p&gt;

&lt;h2&gt;
  
  
  Care and refunds apply even when compensation doesn't
&lt;/h2&gt;

&lt;p&gt;Compensation is only one of your rights. While you wait, the CAA says your airline must provide care "regardless of the reason for the delay" once you've been held up beyond scheduled departure by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;2+ hours&lt;/strong&gt; for flights under 1,500 km&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3+ hours&lt;/strong&gt; for 1,500–3,500 km&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4+ hours&lt;/strong&gt; for over 3,500 km&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Care means food and drink, two calls or emails, and a hotel plus transport if you're delayed overnight. If the airline doesn't arrange it, you can book reasonable care yourself and claim it back. Keep itemised receipts.&lt;/p&gt;

&lt;p&gt;If the delay reaches &lt;strong&gt;five hours&lt;/strong&gt;, you can choose not to travel and get a refund for the flights you haven't taken. Don't choose this if you still want to travel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cancellations&lt;/strong&gt; follow a different logic. You may be owed compensation if you were told less than 14 days before departure, depending on the cause and what replacement flight you were offered.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to claim, step by step
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Collect evidence:&lt;/strong&gt; booking confirmation, boarding passes, the scheduled and actual arrival times, any messages giving the reason, and receipts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claim directly from the airline&lt;/strong&gt; using its own claim form or process. The CAA recommends going to the airline first. It also notes that claim agencies typically charge a fee that "can often be a significant proportion" of the compensation, and that not all airlines will deal with a complaint made through a third party.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalate if needed.&lt;/strong&gt; If you're unhappy with the final response, or the airline hasn't replied within &lt;strong&gt;eight weeks&lt;/strong&gt;, go to the airline's &lt;strong&gt;Alternative Dispute Resolution (ADR)&lt;/strong&gt; body if it belongs to one, or to the &lt;strong&gt;CAA's Passenger Advice and Complaints Team (PACT)&lt;/strong&gt; if not. Note that PACT "cannot impose a decision on an airline", while CAA-approved ADR bodies can.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Court as a last resort.&lt;/strong&gt; The small claims court is usually the right place, and GOV.UK explains &lt;a href="https://www.gov.uk/make-court-claim-for-money" rel="noopener noreferrer"&gt;how to make a court claim for money&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How long do you have?&lt;/strong&gt; UK261 itself doesn't set a deadline. National limitation law applies instead. In England and Wales, contract claims generally have &lt;strong&gt;six years&lt;/strong&gt; (Limitation Act 1980, s.5). In Scotland, the prescriptive period is generally &lt;strong&gt;five years&lt;/strong&gt; (Prescription and Limitation (Scotland) Act 1973, s.6). Don't leave it late, and get advice if you're close to a deadline.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;Arrived 3+ hours late on a covered flight, and the cause was within the airline's control? Then the CAA figures are &lt;strong&gt;£220, £350, £260 or £520 per person&lt;/strong&gt;, depending on distance and, for long-haul, whether you were more or less than four hours late. Claim from the airline yourself first; it costs nothing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article is general information, not legal advice. Figures and quotes were checked against the CAA website on 28 September 2026.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UK CAA: &lt;a href="https://www.caa.co.uk/air-passengers/travel-problems-and-rights/flight-delays-and-cancellations/delays/" rel="noopener noreferrer"&gt;Delays&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;UK CAA: &lt;a href="https://www.caa.co.uk/air-passengers/travel-problems-and-rights/flight-delays-and-cancellations/cancellations/" rel="noopener noreferrer"&gt;Cancellations&lt;/a&gt; (coverage rules, 14-day notice)&lt;/li&gt;
&lt;li&gt;UK CAA: &lt;a href="https://www.caa.co.uk/air-passengers/travel-problems-and-rights/travel-complaints/making-a-claim/am-i-entitled-to-compensation/" rel="noopener noreferrer"&gt;Am I entitled to compensation?&lt;/a&gt; (extraordinary circumstances)&lt;/li&gt;
&lt;li&gt;UK CAA: &lt;a href="https://www.caa.co.uk/air-passengers/travel-problems-and-rights/travel-complaints/how-to-make-a-complaint/" rel="noopener noreferrer"&gt;How to make a complaint&lt;/a&gt; (ADR, PACT, claim agencies)&lt;/li&gt;
&lt;li&gt;UK CAA: &lt;a href="https://www.caa.co.uk/newsroom/news/caa-statement-on-passenger-compensation-following-nats-disruption-on-8-september/" rel="noopener noreferrer"&gt;Statement on passenger compensation following NATS disruption on 8 September&lt;/a&gt; (published 9 Sep 2026)&lt;/li&gt;
&lt;li&gt;UK CAA: &lt;a href="https://www.caa.co.uk/newsroom/news/caa-statement-on-passenger-compensation-following-nats-disruption-on-21-september/" rel="noopener noreferrer"&gt;Statement on passenger compensation following NATS disruption on 21 September&lt;/a&gt; (September 2026)&lt;/li&gt;
&lt;li&gt;GOV.UK: &lt;a href="https://www.gov.uk/make-court-claim-for-money" rel="noopener noreferrer"&gt;Make a court claim for money&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.legislation.gov.uk/ukpga/1980/58/section/5" rel="noopener noreferrer"&gt;Limitation Act 1980, s.5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.legislation.gov.uk/ukpga/1973/52/section/6" rel="noopener noreferrer"&gt;Prescription and Limitation (Scotland) Act 1973, s.6&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I run FlightRefundCalc, a free educational calculator. It is not a law firm or claims company, and it shows an optional, disclosed AirHelp referral that you never need to use.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>travel</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Turning phone update policies into dates: precision, minimums and sources</title>
      <dc:creator>Feroz Sheikh</dc:creator>
      <pubDate>Tue, 29 Sep 2026 05:43:33 +0000</pubDate>
      <link>https://dev.to/shekh_firoj_6217570f10c6c/turning-phone-update-policies-into-dates-precision-minimums-and-sources-4fa8</link>
      <guid>https://dev.to/shekh_firoj_6217570f10c6c/turning-phone-update-policies-into-dates-precision-minimums-and-sources-4fa8</guid>
      <description>&lt;p&gt;"When does this phone stop getting security updates?" sounds like a single date. Once you try to store the answer for hundreds of models, it turns out to be at least four different kinds of fact. I run &lt;a href="https://devlifecheck.com" rel="noopener noreferrer"&gt;DevLifeCheck&lt;/a&gt;, which tracks this for phones, tablets, Chromebooks and routers. These are the modelling decisions that mattered most, using phones as the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manufacturers publish four different shapes of data
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A model-specific end date.&lt;/strong&gt; Some manufacturers publish a table or spec line per model. Xiaomi's product software support page lists an end date for each Xiaomi, Redmi and POCO model, HMD lists one for its Nokia and HMD phones, and Samsung UK product pages carry a "Security Update Period (Valid until)" line. For the Galaxy A56 5G (SM-A566B) it says 31 March 2032.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A duration policy.&lt;/strong&gt; Google says Pixel 8 and later get 7 years of OS and security updates "starting from when the device first became available on the Google Store in the US". Samsung announced seven generations of OS upgrades and seven years of security updates for the Galaxy S24 series. There's no date here. You calculate one from the policy and a start event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A regulatory minimum.&lt;/strong&gt; Under the UK's product security (PSTI) rules, brands such as OPPO, OnePlus, realme and vivo publish the end of a &lt;em&gt;minimum&lt;/em&gt; security-update period for UK models. That is a floor, not a promised last patch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only a cadence.&lt;/strong&gt; Samsung's security site lists models on monthly or quarterly update schedules, and vivo and HONOR publish similar lists. Being on the list tells you the phone is being patched now, not when that will stop. Apple publishes no end dates at all.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you store all four in one &lt;code&gt;end_date&lt;/code&gt; column, your data will be confidently wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Store the meaning and the precision, not just the date
&lt;/h2&gt;

&lt;p&gt;Each support claim gets a small bundle of fields. Simplified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SupportClaim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// ISO 8601, e.g. "2030-10-01"&lt;/span&gt;
  &lt;span class="nl"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DAY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MONTH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YEAR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RANGE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UNKNOWN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;meaning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OFFICIAL_END&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MINIMUM_COMMITMENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ESTIMATE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UNKNOWN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;U&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// A = exact first-party date, B = first-party policy calculation&lt;/span&gt;
  &lt;span class="nl"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                 &lt;span class="c1"&gt;// the market or model code the claim covers&lt;/span&gt;
  &lt;span class="nl"&gt;sourceUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;              &lt;span class="c1"&gt;// first-party page it came from&lt;/span&gt;
  &lt;span class="nl"&gt;checkedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;              &lt;span class="c1"&gt;// when that page was last checked&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Precision matters most for policy-derived dates. Pixel 8 went on sale in the US in October 2023, so seven years lands in &lt;strong&gt;October 2030&lt;/strong&gt;. The stored value is &lt;code&gt;2030-10-01&lt;/code&gt; with &lt;code&gt;MONTH&lt;/code&gt; precision, and the UI must never render it as "1 October 2030". A trimmed response from the public API shows the same idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google-pixel-8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"released"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-10-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"securityEnd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2030-10-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"securityEndPrecision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MONTH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evidenceLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evidenceLabel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Policy-derived"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"supportCalculation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Published policy applied to 2023-10-12; displayed at source-supported precision."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A published model date beats a calculation
&lt;/h2&gt;

&lt;p&gt;The Galaxy A56 5G launched in March 2025 with up to six years of security updates, so the policy points to roughly March 2031. Samsung UK's page for the exact SM-A566B says 31 March 2032. When a first-party source gives a date for a specific model and market, it wins over a calculation, and the record keeps the region it applies to. The same phone sold elsewhere may have a different date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compute status when you read, not when you write
&lt;/h2&gt;

&lt;p&gt;"Supported", "ending soon" and "ended" depend on today's date, so storing them means they go stale. DevLifeCheck derives status at request time from the date, its meaning and a 12-month "ending soon" window. Two rules matter most. When a &lt;strong&gt;minimum&lt;/strong&gt; period has passed, the status becomes &lt;em&gt;unknown&lt;/em&gt;, not &lt;em&gt;ended&lt;/em&gt;, because many phones keep getting patches after their regulatory minimum and "ended" would be a false claim. And a date whose meaning is &lt;code&gt;ESTIMATE&lt;/code&gt; never produces "supported" or "ended" on its own. The status stays &lt;em&gt;unknown&lt;/em&gt; and the date is shown next to its label, so a reader can see how it was derived.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unknown should stay unknown
&lt;/h2&gt;

&lt;p&gt;Of the 712 phones DevLifeCheck currently tracks from 17 brands, 371 have a security end date. The rest have evidence (a cadence list, a UK minimum, an OS-upgrade count) but no final date, and they're shown that way. It's tempting to fill gaps with "the usual" value for a brand. Don't. A blank field with a source link is more useful than a plausible guess, because people use this data to decide whether to buy a used phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try the data
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://devlifecheck.com/developers" rel="noopener noreferrer"&gt;developer page&lt;/a&gt; documents a read-only API (&lt;code&gt;/api/v1/devices&lt;/code&gt;, with a separate evidence endpoint per device) and a CSV export of the published catalog. Every row carries the precision, the date meaning and the source URL. Attribution is required.&lt;/p&gt;

&lt;p&gt;If you've modelled end-of-life data for other hardware, I'd like to hear how you handled minimums versus final dates.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I build and maintain DevLifeCheck.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>security</category>
      <category>opendata</category>
      <category>database</category>
    </item>
  </channel>
</rss>
