<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Puneet Sharma on Medium]]></title>
        <description><![CDATA[Stories by Puneet Sharma on Medium]]></description>
        <link>https://medium.com/@thinkwithpuneet?source=rss-17d5b9ae4aff------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*9UsH95W1SiB-xXtQ6bOAjQ.png</url>
            <title>Stories by Puneet Sharma on Medium</title>
            <link>https://medium.com/@thinkwithpuneet?source=rss-17d5b9ae4aff------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 26 May 2026 22:55:59 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@thinkwithpuneet/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[JavaScript Lied to Me About Time — And I Was Half Right]]></title>
            <link>https://medium.com/@thinkwithpuneet/javascript-lied-to-me-about-time-and-i-was-half-right-c6e774c940a5?source=rss-17d5b9ae4aff------2</link>
            <guid isPermaLink="false">https://medium.com/p/c6e774c940a5</guid>
            <category><![CDATA[backend-development]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[nodejs]]></category>
            <dc:creator><![CDATA[Puneet Sharma]]></dc:creator>
            <pubDate>Fri, 22 May 2026 11:48:15 GMT</pubDate>
            <atom:updated>2026-05-22T11:48:15.239Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z_cGmMWdQzHXXhdP8Cx5AQ.jpeg" /></figure><p><em>An office argument, an NTP rabbit hole, and what payment gateways can teach us about trusting the clock</em></p><p>I was in the middle of a conversation with some colleagues when someone dropped a statement that immediately made me put down my coffee.</p><blockquote>“JavaScript gives wrong time. We should never trust time from JavaScript — always rely on the server.”</blockquote><p>Now I have a personal relationship with JavaScript. (I call it my girlfriend. Don’t judge.) So naturally, I pushed back.</p><p>My argument was simple: <em>JavaScript isn’t lying to you. It’s reading from the system clock. If the system clock is wrong, that’s not JavaScript’s fault. That’s a machine configuration problem.</em> JavaScript is just the messenger. You don’t blame WhatsApp for delivering a wrong message.</p><p>The counter-argument? <em>“It’s still incorrect. In production, you can’t trust it. You haven’t worked on real projects. (also he said javascript is library and node js is a framework - i was like..dammm numb..)”</em></p><p>Wait. Hold on.</p><p>Let’s set aside the personal jab. The technical question is genuinely interesting — and the real answer is more nuanced than either side of that room was willing to admit.</p><p>So let me walk through everything I found when I actually went down this rabbit hole.</p><h3>Round 1: What Does new Date() Actually Do?</h3><p>When you write this in a browser:</p><pre>const now = new Date();<br>console.log(now.toISOString());<br>// 2025-05-22T10:30:00.000Z</pre><p>JavaScript is calling the <strong>system clock of the device running the code</strong>. That’s it. There’s no magic. No satellite connection. No atomic clock ping. It literally asks the OS: <em>“Hey, what time is it?”</em> and the OS says whatever it has been configured to say.</p><p>This means if a user manually changes their laptop clock to 2019, new Date() will happily tell you it&#39;s 2019.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r8CkAUc6QHZ0VhKpT4Wd-A.png" /><figcaption><strong><em>Screenshot of window System Preferences → Date &amp; Time, with “Set date and time automatically” toggle turned OFF — like how easy it is to manipulate system time.</em></strong></figcaption></figure><p>So my colleagues weren’t wrong about the vulnerability. But I wasn’t wrong either — JavaScript isn’t <em>broken</em>. It’s doing exactly what it was designed to do. Garbage in, garbage out.</p><h3>Round 2: The ChatGPT Plot Twist</h3><p>Here’s where the conversation got interesting. Someone pulled out their phone and asked ChatGPT:</p><blockquote>“Hey, does JavaScript give time according to system, and does Node.js give actual time?”</blockquote><p>The answer?</p><blockquote><strong><em>“Not exactly — both JavaScript in the browser and Node.js use the system clock of the machine they are running on.”</em></strong></blockquote><p>The room went quiet.</p><p>Node.js — the “server-side” JavaScript runtime that everyone was claiming gives <em>correct</em> time — <strong>also reads from the system clock</strong>. At the OS level, there is no difference between new Date() in Chrome and new Date() in a Node.js Express server.</p><pre>// Browser<br>console.log(new Date().toISOString()); // Uses OS clock</pre><pre>// Node.js server<br>console.log(new Date().toISOString()); // Also uses OS clock</pre><p>Technically, they are the same call. So why does Node.js feel more trustworthy in production?</p><p>The answer has nothing to do with Node.js itself.</p><h3>The Real Hero: NTP (Network Time Protocol)</h3><p>Here’s the key insight that changes everything.</p><p>When your Node.js app runs on a <strong>production server</strong> — say, a VPS you bought from Hostinger, DigitalOcean, or AWS — that server’s OS clock is <strong>automatically synchronized with the internet</strong> via something called <strong>NTP: Network Time Protocol</strong>.</p><p>You didn’t write a single line of code for this. The cloud provider handled it. Their Linux boxes run an NTP client (like chrony or ntpd) that continuously talks to a hierarchy of highly accurate time servers — ultimately tracing back to atomic clocks maintained by national standards bodies like NIST in the US or NPL in the UK.</p><pre># On a Linux server, you can check NTP sync status:<br>timedatectl status</pre><pre># Output looks like:<br>#      System clock synchronized: yes<br># NTP service: active</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*q4uzkfVCFc9aW8PyFihSFg.jpeg" /></figure><p>This is the real reason server time is more reliable. Not because Node.js is special. Because <strong>servers are usually NTP-synced and user devices often aren’t</strong>.</p><p>A user’s laptop might have “Set time automatically” turned off. Their phone might have been in airplane mode for three days. Your EC2 instance, on the other hand, is in a data center that keeps its clocks accurate to within milliseconds of UTC.</p><p>So the correct framing is:</p><p>Source Uses System Clock?</p><p>Usually NTP-synced?</p><p>Trustworthy for production?</p><p>Browser new Date() ✅ Yes ❓ Maybe ❌ No Node.js new Date() ✅ Yes ✅ Usually ✅ Yes (because of the environment, not the language)</p><h3>So What Do We Actually Do in Code?</h3><p>Let’s get practical. Here are the patterns you should know.</p><h3>1. Never Use Client Time for Critical Logic</h3><p>This is the rule. If you’re calculating order expiry, session timeout, or anything that matters — do it on the server.</p><pre>// ❌ Bad: Trusting the client for time-sensitive logic<br>const orderExpiry = new Date(Date.now() + 30 * 60 * 1000); // 30 minutes from &quot;now&quot;<br>fetch(&#39;/api/place-order&#39;, {<br>  body: JSON.stringify({ expiry: orderExpiry }) // Client-generated timestamp<br>});</pre><pre>// ✅ Good: Let the server decide<br>fetch(&#39;/api/place-order&#39;, {<br>  body: JSON.stringify({ items: cart }) // No timestamp — server will stamp it<br>});</pre><pre>// On the server (Node.js / Express):<br>app.post(&#39;/api/place-order&#39;, (req, res) =&gt; {<br>  const order = {<br>    ...req.body,<br>    createdAt: new Date().toISOString(), // Server-generated, NTP-synced<br>    expiresAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(),<br>  };<br>  // Save to DB...<br>});</pre><h3>2. Always Store Time as UTC</h3><p>This is non-negotiable. Never store &quot;10:30 PM&quot;. Always store &quot;2025-05-22T17:00:00.000Z&quot;. The Z at the end means UTC — a single reference point the entire world agrees on.</p><pre>// ❌ Storing local time — a disaster waiting to happen<br>const timestamp = new Date().toLocaleString(); // &quot;5/22/2025, 10:30:00 PM&quot;<br>// Which timezone? IST? PST? Who knows.</pre><pre>// ✅ Storing UTC — always unambiguous<br>const timestamp = new Date().toISOString(); // &quot;2025-05-22T17:00:00.000Z&quot;</pre><h3>3. Display Time Relative to the User’s Locale — Let the Browser Handle It</h3><p>Here’s the beautiful part. Once your backend stores everything in UTC, the browser can automatically convert it to the user’s local timezone. You don’t have to write timezone conversion logic.</p><pre>// You get this UTC string from your API:<br>const utcTimestamp = &quot;2025-05-22T17:00:00.000Z&quot;;</pre><pre>// Display it in the user&#39;s local timezone automatically:<br>const localDate = new Date(utcTimestamp);<br>console.log(localDate.toLocaleString()); <br>// In India: &quot;22/5/2025, 10:30:00 pm&quot;<br>// In New York: &quot;5/22/2025, 1:00:00 PM&quot;<br>// In London: &quot;22/05/2025, 18:00:00&quot;</pre><p>The browser reads the device timezone and converts accordingly. Physics is doing the work — time is relative to the observer’s location, and JavaScript’s toLocaleString() handles that relativity correctly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*htbJ-O5jtipfMyJG93wD_A.jpeg" /></figure><h3>4. Use a Proper Date Library for Complex Operations</h3><p>For anything beyond basic display — date arithmetic, duration formatting, timezone-aware comparisons — use a battle-tested library.</p><pre>// Using date-fns (lightweight, tree-shakeable)<br>import { formatDistanceToNow, isAfter, parseISO } from &#39;date-fns&#39;;</pre><pre>const orderTime = parseISO(&quot;2025-05-22T10:00:00.000Z&quot;);</pre><pre>console.log(formatDistanceToNow(orderTime)); <br>// &quot;about 2 hours ago&quot;</pre><pre>const deadline = parseISO(&quot;2025-05-22T12:00:00.000Z&quot;);<br>if (isAfter(new Date(), deadline)) {<br>  console.log(&quot;Order window has closed.&quot;);<br>}</pre><h3>The Payment Gateway Story: Where Time Gets Wild</h3><p>This is the part I find genuinely fascinating.</p><p>When you make a payment — say, an EMI that’s due on May 31st at 11:59 PM — <em>which</em> 11:59 PM counts? The payment gateway is in a data center in Mumbai. The bank’s server might be in Pune. You’re making the payment from your phone in Jaipur. Your payment app is showing time from its own servers.</p><p>How do these systems avoid chaos?</p><h3>The Answer: Epoch Timestamps + UTC Reference</h3><p>Every serious payment system stores and compares times as <strong>Unix epoch milliseconds</strong> — the number of milliseconds since January 1, 1970, 00:00:00 UTC. It’s a single integer. No timezone ambiguity. No DST confusion.</p><pre>// Instead of comparing &quot;May 31st 11:59 PM IST&quot;<br>// They compare epoch values:</pre><pre>const dueDate = 1748703540000; // A specific UTC moment in epoch ms<br>const paymentTime = Date.now(); // Server-generated epoch ms (NTP-synced)</pre><pre>if (paymentTime &lt;= dueDate) {<br>  // Payment is on time ✅<br>} else {<br>  // Payment is late ❌<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mz-a0B0nuPuTFF6TMYIkGA.jpeg" /></figure><h3>The Grace Period Problem</h3><p>Here’s a real story-worthy edge case. Imagine two things happen simultaneously:</p><ul><li>At T = 0ms: The payment gateway server logs your payment as received</li><li>At T = +200ms: The bank&#39;s server processes the transaction and stamps it</li></ul><p>Those 200 milliseconds could push a payment from “before midnight” to “after midnight” depending on which timestamp is considered authoritative. This is why payment systems define a <strong>canonical timestamp source</strong> — usually one authoritative service that all parties agree to use — and build in grace periods (often 5–15 minutes) for exactly these clock-skew scenarios.</p><p>RBI guidelines, for example, require payment systems to maintain time synchronization within acceptable bounds precisely because of this.</p><p>This is also why in your EMI apps you’ll sometimes see “Last date: May 31 — payments accepted until 11:59 PM IST” but the actual cutoff in the system might be 12:05 AM June 1 UTC — the grace window accounting for clock skew across systems.</p><h3>Summary: The Cheat Sheet</h3><p>Let me save you the office argument next time:</p><pre>1. JavaScript&#39;s new Date() → reads system clock (always)<br>2. Node.js new Date()     → also reads system clock (always)<br>3. Server time &gt; Client time → because servers are NTP-synced, not because of the language<br>4. Store everything in UTC (ISO 8601 format)<br>5. Display using toLocaleString() — let the browser handle timezone conversion<br>6. Critical comparisons → use epoch milliseconds on the server side<br>7. Payment systems → define one canonical time source + build in grace periods</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MesvZhqSyOhpomTfXLfNug.jpeg" /></figure><h3>Final Thought</h3><p>The person who said “JavaScript gives wrong time” was pointing at a real problem — but misattributing the cause. JavaScript is faithfully reporting what the machine tells it. The machine is the unreliable one.</p><p>And the person who said “Node.js gives actual time” was right in <em>practice</em> — but wrong in theory. It’s the server environment, not Node.js itself, that makes the difference.</p><p>The real lesson? <strong>Time is a distributed systems problem.</strong> The moment you have two machines that need to agree on “when” something happened, you’ve entered a world of NTP hierarchies, epoch timestamps, clock skew, and grace periods.</p><p>And JavaScript, my faithful girlfriend, is just caught in the middle.</p><p><em>If you found this useful, drop a clap (or 50 — they’re free 😄). I’ll be writing more about the hidden complexity inside everyday web development. Next up: how do session tokens handle expiry when the server clock drifts?</em></p><p><strong>Tags:</strong> JavaScript Node.js Web Development Backend Software Engineering</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c6e774c940a5" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>