<?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: Saad Tahir</title>
    <description>The latest articles on DEV Community by Saad Tahir (@saadtahir976).</description>
    <link>https://dev.to/saadtahir976</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%2F4010085%2F3bfb5bae-7d50-4acc-af6d-16f09f8efafd.png</url>
      <title>DEV Community: Saad Tahir</title>
      <link>https://dev.to/saadtahir976</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saadtahir976"/>
    <language>en</language>
    <item>
      <title>Why Hijri Date Conversion Breaks Naive Math Formulas</title>
      <dc:creator>Saad Tahir</dc:creator>
      <pubDate>Wed, 01 Jul 2026 18:18:46 +0000</pubDate>
      <link>https://dev.to/saadtahir976/why-hijri-date-conversion-breaks-naive-math-formulas-5bh7</link>
      <guid>https://dev.to/saadtahir976/why-hijri-date-conversion-breaks-naive-math-formulas-5bh7</guid>
      <description>&lt;p&gt;If you search "convert Gregorian to Hijri" you'll find dozens of one-line formulas floating around StackOverflow, most of them some variant of &lt;code&gt;hijriYear = (gregorianYear - 622) * 33 / 32&lt;/code&gt;. They compile, they run, and they're wrong more often than they're right. Here's why, and what a correct implementation actually needs to account for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core problem: Hijri is observational, not purely arithmetic
&lt;/h2&gt;

&lt;p&gt;The Gregorian calendar is a fixed solar calendar: every year is either 365 or 366 days, decided by a simple leap-year rule. The Hijri calendar is lunar, and a lunar month is roughly 29.53 days. That means a Hijri year runs about 354 or 355 days, roughly 10-11 days shorter than a Gregorian year.&lt;/p&gt;

&lt;p&gt;A linear ratio formula assumes that gap grows at a constant rate. It doesn't. Two people born in the same Gregorian year can land in different Hijri years depending on which month and day they were born, because the drift accumulates unevenly across the year, not proportionally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "tabular" Islamic calendars aren't the same as Umm al-Qura
&lt;/h2&gt;

&lt;p&gt;There are actually multiple standardized Hijri calendar systems. Some countries use a "tabular" Islamic calendar with a fixed 30-year leap cycle (11 leap years out of 30), which is arithmetically predictable. Saudi Arabia's official calendar, Umm al-Qura, is based on astronomical calculations of lunar visibility, and its month lengths don't always match the tabular system.&lt;/p&gt;

&lt;p&gt;This matters a lot if you're building anything that needs to be accurate for Saudi users specifically: government paperwork, religious dates, retirement age calculations, school enrollment cutoffs. A generic tabular-calendar library will silently disagree with the real Umm al-Qura calendar on certain dates, sometimes by a full day, which shifts the reported Hijri date entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an accurate implementation actually needs
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A proper day-count conversion (Julian Day Number as the intermediate step) instead of a year-level ratio&lt;/li&gt;
&lt;li&gt;Support for the specific Hijri variant you need (tabular vs Umm al-Qura), since they diverge&lt;/li&gt;
&lt;li&gt;Testing against known reference dates, not just internal consistency&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I ended up building this into a small web tool rather than reinventing it for every project. If you want to see it in action, there's a free &lt;a href="https://agecalculator360.com/date-converter.html" rel="noopener noreferrer"&gt;Hijri-Gregorian date converter&lt;/a&gt; that does the Julian Day Number conversion under the hood and follows the official Umm al-Qura calendar, plus an &lt;a href="https://agecalculator360.com/hijri-age-calculator.html" rel="noopener noreferrer"&gt;age calculator that handles the Hijri/Gregorian gap correctly&lt;/a&gt; instead of using the flawed ratio shortcut.&lt;/p&gt;

&lt;p&gt;If you're implementing this yourself, the short version is: don't multiply, count days.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>coding</category>
      <category>computerscience</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building a Hijri-Gregorian Date Calculator: Lessons from an Arabic Web Tool</title>
      <dc:creator>Saad Tahir</dc:creator>
      <pubDate>Tue, 30 Jun 2026 20:51:37 +0000</pubDate>
      <link>https://dev.to/saadtahir976/building-a-hijri-gregorian-date-calculator-lessons-from-an-arabic-web-tool-539f</link>
      <guid>https://dev.to/saadtahir976/building-a-hijri-gregorian-date-calculator-lessons-from-an-arabic-web-tool-539f</guid>
      <description>&lt;p&gt;If you've ever tried to build a date calculator for Arabic-speaking users, you've likely run into one frustrating problem: the Gregorian calendar isn't the only game in town.&lt;/p&gt;

&lt;p&gt;Across Saudi Arabia, the Gulf, and much of the Arab world, the &lt;strong&gt;Hijri (Islamic) calendar&lt;/strong&gt; is used daily — for religious occasions, official government documents, birth certificates, and even age verification. Building &lt;a href="https://agecalculator360.com" rel="noopener noreferrer"&gt;agecalculator360.com&lt;/a&gt; taught me a lot about these differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes the Hijri Calendar Different?
&lt;/h2&gt;

&lt;p&gt;The Hijri calendar is a &lt;strong&gt;purely lunar calendar&lt;/strong&gt;, meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each month starts with the new crescent moon&lt;/li&gt;
&lt;li&gt;Months alternate between 29 and 30 days&lt;/li&gt;
&lt;li&gt;A Hijri year is approximately &lt;strong&gt;354 days&lt;/strong&gt; — about 11 days shorter than a Gregorian year&lt;/li&gt;
&lt;li&gt;This means a person's Hijri age is always slightly older than their Gregorian age&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This also means &lt;strong&gt;date conversion isn't a simple formula&lt;/strong&gt;. You can't just multiply by a constant.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Two Hijri Systems
&lt;/h2&gt;

&lt;p&gt;This is where it gets tricky. There are actually two main Hijri calendar systems used in software:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Tabular Islamic Calendar
&lt;/h3&gt;

&lt;p&gt;A purely algorithmic calendar used by most JavaScript libraries. It follows a fixed 30-year cycle pattern. It's consistent, but it can be off by 1–2 days from the official calendar used in Saudi Arabia.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Umm Al-Qura Calendar
&lt;/h3&gt;

&lt;p&gt;The official calendar of Saudi Arabia, maintained by the King Abdulaziz City for Science and Technology (KACST). This one is based on &lt;strong&gt;astronomical calculations&lt;/strong&gt; and is what all Saudi government systems use for official age verification.&lt;/p&gt;

&lt;p&gt;If you're building tools for Saudi Arabia or the Gulf region, using the tabular system will give users wrong results on documents that matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Implementation Challenges
&lt;/h2&gt;

&lt;p&gt;Here's what I ran into building the &lt;a href="https://agecalculator360.com/hijri-age-calculator.html" rel="noopener noreferrer"&gt;Hijri age calculator&lt;/a&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  No Standard Library
&lt;/h3&gt;

&lt;p&gt;The most popular Hijri calendar libraries (moment-hijri, hijri-js) default to the tabular system. For the Umm Al-Qura calendar, you need to either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintain a lookup table of month lengths (which KACST publishes)&lt;/li&gt;
&lt;li&gt;Implement the astronomical algorithm yourself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I opted for the lookup table approach, which makes the code larger but guarantees accuracy for current and near-future dates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Age Calculation Edge Cases
&lt;/h3&gt;

&lt;p&gt;Computing someone's age in Hijri has a subtle edge case: because Hijri months vary in length (29 or 30 days), two people born on the "same day" in different years might have different day counts in their birth month.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;hijriAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;birthMonth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;birthDay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todayYear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todayMonth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todayDay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;years&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todayYear&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;months&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todayMonth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;birthMonth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todayDay&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;birthDay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;months&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Get days in previous Hijri month (29 or 30, not fixed!)&lt;/span&gt;
    &lt;span class="nx"&gt;days&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;getHijriMonthLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todayYear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todayMonth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;months&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;years&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;months&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;years&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;months&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;getHijriMonthLength()&lt;/code&gt; function is what requires the Umm Al-Qura lookup table — you can't calculate it from a formula alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dual Calendar Display
&lt;/h3&gt;

&lt;p&gt;Many Arabic users want to see their age &lt;strong&gt;in both calendars simultaneously&lt;/strong&gt;. This is actually a feature, not a complication. Our &lt;a href="https://agecalculator360.com/date-converter.html" rel="noopener noreferrer"&gt;date converter tool&lt;/a&gt; shows both Hijri and Gregorian equivalents side by side.&lt;/p&gt;

&lt;p&gt;The UX lesson: don't make users choose. Show both.&lt;/p&gt;

&lt;h2&gt;
  
  
  RTL and Arabic Numeral Considerations
&lt;/h2&gt;

&lt;p&gt;A quick note on display: if you're building for Arabic audiences, remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;Western digits (0-9)&lt;/strong&gt;, not Eastern Arabic digits (٠-٩) — most Arabic users prefer Western digits in numeric contexts&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;dir="rtl"&lt;/code&gt; attribute on your HTML element handles text direction&lt;/li&gt;
&lt;li&gt;Google Fonts has excellent Arabic-supporting fonts: &lt;strong&gt;Cairo&lt;/strong&gt; and &lt;strong&gt;Readex Pro&lt;/strong&gt; are both readable and load fast&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;After working through these challenges, the tool now handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Age calculation in both Hijri and Gregorian simultaneously&lt;/li&gt;
&lt;li&gt;Support for dates back to 1930 CE / 1348 AH&lt;/li&gt;
&lt;li&gt;School enrollment age calculation based on Saudi education ministry rules&lt;/li&gt;
&lt;li&gt;Retirement age calculation for Saudi Arabia and 6 other Arab countries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building date tools for the Arab world, I hope this saves you some debugging time!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
