<?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: Julian Halden</title>
    <description>The latest articles on DEV Community by Julian Halden (@julianhalden).</description>
    <link>https://dev.to/julianhalden</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%2F4143599%2F7bca5d3a-3889-4f25-a43a-e47ce4c7a315.png</url>
      <title>DEV Community: Julian Halden</title>
      <link>https://dev.to/julianhalden</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/julianhalden"/>
    <language>en</language>
    <item>
      <title>Unix Timestamps Explained: Seconds, Milliseconds, Time Zones and Common Mistakes</title>
      <dc:creator>Julian Halden</dc:creator>
      <pubDate>Fri, 25 Sep 2026 23:56:59 +0000</pubDate>
      <link>https://dev.to/julianhalden/unix-timestamps-explained-seconds-milliseconds-time-zones-and-common-mistakes-1p9c</link>
      <guid>https://dev.to/julianhalden/unix-timestamps-explained-seconds-milliseconds-time-zones-and-common-mistakes-1p9c</guid>
      <description>&lt;p&gt;Unix timestamps are everywhere. APIs, databases, logs, JavaScript and authentication tokens all use them, and they cause a surprising number of bugs.&lt;/p&gt;

&lt;p&gt;Is &lt;code&gt;1790186400&lt;/code&gt; a date? What about &lt;code&gt;1790186400000&lt;/code&gt;? Does a Unix timestamp contain a time zone? Why does JavaScript sometimes show a date in your local time when the timestamp itself is supposed to be UTC?&lt;/p&gt;

&lt;p&gt;This article explains how Unix timestamps actually work, the difference between seconds and milliseconds, how time zones fit into the picture, and the mistakes developers most commonly make.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is a Unix timestamp?&lt;/li&gt;
&lt;li&gt;Seconds vs milliseconds&lt;/li&gt;
&lt;li&gt;JavaScript uses milliseconds&lt;/li&gt;
&lt;li&gt;Does a Unix timestamp have a time zone?&lt;/li&gt;
&lt;li&gt;UTC vs local time&lt;/li&gt;
&lt;li&gt;ISO 8601 and Unix timestamps are different things&lt;/li&gt;
&lt;li&gt;Common mistakes

&lt;ul&gt;
&lt;li&gt;#1: Mixing seconds and milliseconds&lt;/li&gt;
&lt;li&gt;#2: Assuming the timestamp is in local time&lt;/li&gt;
&lt;li&gt;#3: Removing the UTC indicator&lt;/li&gt;
&lt;li&gt;#4: Manually applying time-zone offsets&lt;/li&gt;
&lt;li&gt;#5: Ignoring daylight saving time&lt;/li&gt;
&lt;li&gt;#6: Storing local time instead of an instant&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Not every date should be a Unix timestamp&lt;/li&gt;
&lt;li&gt;Negative Unix timestamps&lt;/li&gt;
&lt;li&gt;What about the Year 2038 problem?&lt;/li&gt;
&lt;li&gt;Notable Unix timestamps&lt;/li&gt;
&lt;li&gt;Unix timestamp precision&lt;/li&gt;
&lt;li&gt;Converting Unix timestamps in JavaScript&lt;/li&gt;
&lt;li&gt;Debugging an unknown timestamp&lt;/li&gt;
&lt;li&gt;A good rule for APIs&lt;/li&gt;
&lt;li&gt;Practical rules to remember&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a Unix timestamp?
&lt;/h2&gt;

&lt;p&gt;A Unix timestamp represents the amount of time that has passed since January 1, 1970 at 00:00:00 UTC. This moment is commonly called the &lt;strong&gt;Unix epoch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9do0q8ydbvotl7d9e6gx.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9do0q8ydbvotl7d9e6gx.webp" alt="Unix timestamp timeline from the 1970 Unix epoch to the Year 2038 limit" width="799" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;0&lt;/code&gt; represents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1970-01-01 00:00:00 UTC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A timestamp such as &lt;code&gt;1790186400&lt;/code&gt; represents a specific moment after the Unix epoch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-23 18:00:00 UTC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is that the timestamp represents an &lt;strong&gt;instant in time&lt;/strong&gt;, not a formatted date. A value such as &lt;code&gt;2026-09-23 18:00:00&lt;/code&gt; is a human-readable representation. A Unix timestamp is simply a number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seconds vs milliseconds
&lt;/h2&gt;

&lt;p&gt;One of the most common timestamp bugs comes from confusing seconds with milliseconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj83xe98jtd2jwrygpjez.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj83xe98jtd2jwrygpjez.webp" alt="Unix timestamp seconds vs milliseconds comparison with 10-digit and 13-digit examples" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traditional Unix timestamps use seconds since January 1, 1970. Many programming environments, however, use milliseconds. The same instant looks like this in each unit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Seconds:      1790186400
Milliseconds: 1790186400000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Milliseconds usually have three extra digits. A quick rule of thumb:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10 digits -&amp;gt; usually seconds
13 digits -&amp;gt; usually milliseconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works for modern dates, but you should not rely on digit count as formal validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript uses milliseconds
&lt;/h2&gt;

&lt;p&gt;JavaScript's &lt;code&gt;Date&lt;/code&gt; API expects milliseconds:&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;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1790186400000&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But many APIs return Unix timestamps in seconds:&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;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1790186400&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you pass that directly to &lt;code&gt;Date&lt;/code&gt;, JavaScript interprets it as milliseconds, and the resulting date lands in January 1970:&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1790186400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 1970-01-21T17:16:26.400Z&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, convert seconds to milliseconds:&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;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1790186400&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reverse operation works the same way. To get the current Unix timestamp in seconds:&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;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get milliseconds:&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;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Does a Unix timestamp have a time zone?
&lt;/h2&gt;

&lt;p&gt;No. This is one of the most important things to understand about timestamps.&lt;/p&gt;

&lt;p&gt;A Unix timestamp does not contain a time zone. It represents one exact instant in time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Futc6jpj2yyth0cettjpl.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Futc6jpj2yyth0cettjpl.webp" alt="The same Unix timestamp displayed in Calgary, New York, London, and Tokyo time zones" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;1790186400&lt;/code&gt; represents &lt;code&gt;2026-09-23 18:00:00 UTC&lt;/code&gt;. The exact same instant can be displayed as:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;th&gt;Local time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Calgary&lt;/td&gt;
&lt;td&gt;2026-09-23 12:00:00 MDT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New York&lt;/td&gt;
&lt;td&gt;2026-09-23 14:00:00 EDT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;London&lt;/td&gt;
&lt;td&gt;2026-09-23 19:00:00 BST&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The timestamp does not change. Only its formatted representation changes.&lt;/p&gt;

&lt;p&gt;Think of a Unix timestamp as a position on a global timeline. A time zone only changes how that position is displayed to a person.&lt;/p&gt;

&lt;h2&gt;
  
  
  UTC vs local time
&lt;/h2&gt;

&lt;p&gt;JavaScript makes this distinction visible:&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;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1790186400000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;toISOString()&lt;/code&gt; returns the date in UTC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-23T18:00:00.000Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Z&lt;/code&gt; means UTC. But &lt;code&gt;toString()&lt;/code&gt; uses the computer's local time zone:&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A developer in Calgary might see something similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Wed Sep 23 2026 12:00:00 GMT-0600 (Mountain Daylight Time)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both values represent the exact same instant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw76bbvqfqskckh73x885.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw76bbvqfqskckh73x885.webp" alt="Unix timestamp shown as different local times in multiple time zones with UTC conversion" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This difference is responsible for many apparent "timezone bugs". The timestamp is often correct — what changed is the way the application formatted it.&lt;/p&gt;

&lt;h2&gt;
  
  
  ISO 8601 and Unix timestamps are different things
&lt;/h2&gt;

&lt;p&gt;Developers sometimes mix up Unix timestamps and ISO 8601 dates.&lt;/p&gt;

&lt;p&gt;A Unix timestamp looks like &lt;code&gt;1790186400&lt;/code&gt;. An ISO 8601 date looks like &lt;code&gt;2026-09-23T18:00:00Z&lt;/code&gt;. They can both represent the same instant — the difference is representation.&lt;/p&gt;

&lt;p&gt;Unix timestamps are compact and convenient for machines. ISO 8601 strings are easier for humans to read and can explicitly contain a UTC offset. For example, these two strings represent the same moment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-23T12:00:00-06:00
2026-09-23T18:00:00Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common mistake #1: mixing seconds and milliseconds
&lt;/h2&gt;

&lt;p&gt;Consider an API response:&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;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1790186400&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;p&gt;You might write:&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;const&lt;/span&gt; &lt;span class="nx"&gt;createdAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is wrong if &lt;code&gt;created_at&lt;/code&gt; uses Unix seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbkd4gbjzwjs8dk7snbjj.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbkd4gbjzwjs8dk7snbjj.webp" alt="JavaScript Unix timestamp mistake caused by passing seconds instead of milliseconds to Date" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The correct version is:&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;const&lt;/span&gt; &lt;span class="nx"&gt;createdAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reverse mistake happens as well. Suppose an API expects seconds, and you write:&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;const&lt;/span&gt; &lt;span class="nx"&gt;expiresAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You send &lt;code&gt;1790186400000&lt;/code&gt;, but the server expects &lt;code&gt;1790186400&lt;/code&gt;. Read as seconds, your expiration date suddenly lands tens of thousands of years in the future.&lt;/p&gt;

&lt;p&gt;When working with timestamps, always check the API documentation for the expected unit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistake #2: assuming the timestamp is in local time
&lt;/h2&gt;

&lt;p&gt;A timestamp does not mean "12:00 Calgary time" or "14:00 New York time". It represents a global instant. The time zone matters only when converting that instant into a calendar date and clock time.&lt;/p&gt;

&lt;p&gt;This distinction becomes especially important when users are located in different countries. For example, your database might store &lt;code&gt;1790186400&lt;/code&gt;, and the frontend then displays that timestamp in each user's own time zone. That is usually much safer than storing separately formatted local dates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistake #3: removing the UTC indicator
&lt;/h2&gt;

&lt;p&gt;Consider this ISO string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-23T18:00:00Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Z&lt;/code&gt; tells the parser that the value is UTC. Compare it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-23T18:00:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no time-zone information here. Depending on the language, library, environment or parsing rules, the second value may be interpreted differently — in JavaScript, for example, a date-time string without an offset is parsed as local time.&lt;/p&gt;

&lt;p&gt;When exchanging dates between systems, explicit time-zone information is much safer. Prefer formats such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-23T18:00:00Z
2026-09-23T12:00:00-06:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of an ambiguous local date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistake #4: manually applying time-zone offsets
&lt;/h2&gt;

&lt;p&gt;Imagine you receive a timestamp from an API and convert it to a JavaScript &lt;code&gt;Date&lt;/code&gt;. JavaScript already knows how to display that date in the local time zone. A common mistake is then manually adding or subtracting an offset:&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;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In many cases this applies the time-zone conversion twice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmmioom5f9yn516mameyi.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmmioom5f9yn516mameyi.webp" alt="Correct and incorrect ways to convert Unix timestamps between UTC and local time in JavaScript" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also breaks when daylight saving time changes.&lt;/p&gt;

&lt;p&gt;Instead, keep the underlying timestamp unchanged and apply the desired time zone only when formatting the value:&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;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formatted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-CA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dateStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;America/Edmonton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much safer than manually adding or subtracting hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistake #5: ignoring daylight saving time
&lt;/h2&gt;

&lt;p&gt;Time-zone offsets are not always constant. A location might use one UTC offset during part of the year and another during the rest of the year. Because of that, code such as:&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="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should not be used as a general way to convert UTC to a local time zone. The correct offset may depend on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;location;&lt;/li&gt;
&lt;li&gt;date;&lt;/li&gt;
&lt;li&gt;daylight saving rules;&lt;/li&gt;
&lt;li&gt;historical time-zone changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use an actual IANA time-zone identifier instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;America/Edmonton
America/New_York
Europe/London
Asia/Tokyo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modern date/time libraries and &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; apply the appropriate rules for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistake #6: storing local time instead of an instant
&lt;/h2&gt;

&lt;p&gt;Imagine a database field contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-09-23 12:00:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does that mean? 12:00 where — Calgary, Toronto, London, UTC? Without additional information, the value is ambiguous.&lt;/p&gt;

&lt;p&gt;For events that represent an exact moment, storing either a Unix timestamp or an explicitly UTC-based datetime usually avoids this problem. Values such as &lt;code&gt;1790186400&lt;/code&gt; or &lt;code&gt;2026-09-23T18:00:00Z&lt;/code&gt; can be converted into the user's preferred local time later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not every date should be a Unix timestamp
&lt;/h2&gt;

&lt;p&gt;There is an important exception: some dates do not represent a global instant.&lt;/p&gt;

&lt;p&gt;A birthday is a good example. If someone was born on &lt;code&gt;1990-05-15&lt;/code&gt;, you care about the calendar date, not an exact UTC moment. The same applies to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;birthdays;&lt;/li&gt;
&lt;li&gt;anniversaries;&lt;/li&gt;
&lt;li&gt;all-day calendar events;&lt;/li&gt;
&lt;li&gt;billing dates;&lt;/li&gt;
&lt;li&gt;holidays.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Converting every date into a timestamp can introduce unnecessary time-zone problems — a birthday stored as midnight UTC can show up as the previous day for users west of Greenwich. Choose the representation based on what the value actually means.&lt;/p&gt;

&lt;h2&gt;
  
  
  Negative Unix timestamps
&lt;/h2&gt;

&lt;p&gt;Dates before January 1, 1970 are represented with negative timestamps. For example, &lt;code&gt;-1&lt;/code&gt; represents one second before the Unix epoch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1969-12-31 23:59:59 UTC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many modern systems support negative Unix timestamps, but behavior can differ between platforms and older libraries. If your application works with historical dates, test them explicitly. The lower limit of 32-bit time is covered in Unix timestamp -2147483648 and the 1901 limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the Year 2038 problem?
&lt;/h2&gt;

&lt;p&gt;A signed 32-bit integer can store values only up to &lt;code&gt;2147483647&lt;/code&gt;. Interpreted as seconds since the Unix epoch, that limit is reached on January 19, 2038 at 03:14:07 UTC. Older systems that store timestamps as signed 32-bit integers overflow after that point.&lt;/p&gt;

&lt;p&gt;Modern 64-bit systems do not have this practical limitation — a signed 64-bit timestamp in seconds covers a range far beyond anything normal applications need. However, the 2038 problem can still matter when working with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;legacy operating systems;&lt;/li&gt;
&lt;li&gt;embedded systems;&lt;/li&gt;
&lt;li&gt;old databases;&lt;/li&gt;
&lt;li&gt;binary protocols;&lt;/li&gt;
&lt;li&gt;older C applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Notable Unix timestamps
&lt;/h2&gt;

&lt;p&gt;A few values come up again and again in logs, tests and bug reports:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Timestamp&lt;/th&gt;
&lt;th&gt;Date (UTC)&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-2147483648&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1901-12-13 20:45:52&lt;/td&gt;
&lt;td&gt;Signed 32-bit minimum and 2038 overflow target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1970-01-01 00:00:00&lt;/td&gt;
&lt;td&gt;The Unix epoch, and why buggy dates show 1970&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1000000000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2001-09-09 01:46:40&lt;/td&gt;
&lt;td&gt;The billennium: timestamps become 10 digits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1234567890&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2009-02-13 23:31:30&lt;/td&gt;
&lt;td&gt;The famous sequential timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1700000000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2023-11-14 22:13:20&lt;/td&gt;
&lt;td&gt;Round-number milestones from 1.5 to 2.1 billion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2000000000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2033-05-18 03:33:20&lt;/td&gt;
&lt;td&gt;The last round billion before 2038&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2147483647&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2038-01-19 03:14:07&lt;/td&gt;
&lt;td&gt;The Year 2038 problem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;4294967295&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2106-02-07 06:28:15&lt;/td&gt;
&lt;td&gt;The unsigned 32-bit limit and Year 2106&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Unix timestamp precision
&lt;/h2&gt;

&lt;p&gt;Unix-style timestamps can use different levels of precision. The same instant in each unit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Seconds:      1790186400
Milliseconds: 1790186400000
Microseconds: 1790186400000000
Nanoseconds:  1790186400000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why receiving "a timestamp" from an API is not enough information. Before parsing it, check whether the value represents seconds, milliseconds, microseconds or nanoseconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting Unix timestamps in JavaScript
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Timestamp in seconds to Date
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1790186400&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Timestamp in milliseconds to Date
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1790186400000&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Current Unix timestamp in seconds
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Current Unix timestamp in milliseconds
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Date to Unix seconds
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Convert to UTC ISO format
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1790186400000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// 2026-09-23T18:00:00.000Z&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Debugging an unknown timestamp
&lt;/h2&gt;

&lt;p&gt;Suppose you find &lt;code&gt;1790186400&lt;/code&gt; in a log and do not know what it means. A useful debugging process is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Determine whether it is probably seconds, milliseconds, microseconds or nanoseconds.&lt;/li&gt;
&lt;li&gt;Convert it into UTC.&lt;/li&gt;
&lt;li&gt;Compare the result with the expected date.&lt;/li&gt;
&lt;li&gt;Check whether the system displays the result in local time.&lt;/li&gt;
&lt;li&gt;Look for any manually applied time-zone offsets.&lt;/li&gt;
&lt;li&gt;Verify how the originating API or database documents the field.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For quick debugging, use the &lt;a href="https://helpers.work/tool/timestamp" rel="noopener noreferrer"&gt;Unix Timestamp Converter&lt;/a&gt; to convert between Unix timestamps and human-readable dates in any time zone.&lt;/p&gt;

&lt;h2&gt;
  
  
  A good rule for APIs
&lt;/h2&gt;

&lt;p&gt;When designing APIs, consistency matters more than which representation you choose. You might decide that your API always returns ISO 8601 strings:&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;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-23T18:00:00Z"&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;p&gt;Or you might use Unix timestamps:&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;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1790186400&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;p&gt;Both approaches work. Problems begin when one endpoint returns seconds (&lt;code&gt;1790186400&lt;/code&gt;), another returns milliseconds (&lt;code&gt;1790186400000&lt;/code&gt;), and a third returns a local datetime (&lt;code&gt;2026-09-23 12:00:00&lt;/code&gt;) without documenting the difference.&lt;/p&gt;

&lt;p&gt;Pick a convention and use it consistently across your API. The same applies to tokens: the &lt;code&gt;exp&lt;/code&gt;, &lt;code&gt;iat&lt;/code&gt; and &lt;code&gt;nbf&lt;/code&gt; claims in a JWT are always Unix seconds, which you can check with the &lt;a href="https://helpers.work/tool/jwt-decoder" rel="noopener noreferrer"&gt;JWT Decoder&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical rules to remember
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Unix timestamp represents an instant in time.&lt;/li&gt;
&lt;li&gt;Unix timestamps do not contain a time zone.&lt;/li&gt;
&lt;li&gt;Traditional Unix timestamps use seconds.&lt;/li&gt;
&lt;li&gt;JavaScript timestamps normally use milliseconds.&lt;/li&gt;
&lt;li&gt;Do not apply fixed UTC offsets manually when you can use a real time-zone database.&lt;/li&gt;
&lt;li&gt;Store exact moments in a time-zone-independent format.&lt;/li&gt;
&lt;li&gt;Convert to the user's local time only when displaying the value.&lt;/li&gt;
&lt;li&gt;Use explicit time-zone information when exchanging formatted datetime strings.&lt;/li&gt;
&lt;li&gt;Always verify the timestamp unit used by an API.&lt;/li&gt;
&lt;li&gt;Do not use timestamps for calendar-only dates unless you actually need an instant in time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Unix timestamps are simple numbers, but the systems around them — time zones, daylight saving time, date formatting and different precision levels — make them surprisingly easy to misuse.&lt;/p&gt;

&lt;p&gt;The most useful mental model is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A Unix timestamp identifies a point on the global timeline. A time zone only determines how that point is displayed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you separate those two ideas, most timestamp problems become much easier to understand and debug.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://helpers.work/blog/unix-timestamps" rel="noopener noreferrer"&gt;helpers.work&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
