Try the Timestamp Converter

Unix Timestamps and Timezone Bugs: What Every Developer Should Know

Timezone bugs cause more production incidents than most developers realise. Here's how Unix timestamps actually work, why "store UTC, convert at display" solves the problem, and the specific bugs that catch teams off guard.

By sadiqbd Β· June 8, 2026

Share:
Unix Timestamps and Timezone Bugs: What Every Developer Should Know

Datetime handling is responsible for a disproportionate share of production bugs

The code works perfectly in development. In staging. In every test. Then it goes to production and users in a different timezone start seeing events on the wrong day, scheduled jobs run at the wrong time, and report totals don't match because midnight means different things to different servers.

Unix timestamps don't cause these problems. Misunderstanding them does.


What a Unix timestamp actually is

A Unix timestamp is the number of seconds (or milliseconds, depending on context) elapsed since the Unix epoch: January 1, 1970, 00:00:00 UTC. Not midnight local time β€” midnight UTC, specifically.

Current timestamp at the time of writing: approximately 1,718,000,000 seconds. That number is the same right now in Berlin, New York, Sydney, and Tokyo. It has no timezone. It has no concept of daylight saving. It's just a count of elapsed seconds from a fixed point in history.

This is why timestamps are the correct way to store and transmit time in any system where more than one timezone is involved.


The timestamp converter: what it does

The converter handles two operations:

Unix timestamp β†’ human-readable date: 1718000000 β†’ 2024-06-10 08:53:20 UTC

Human-readable date β†’ Unix timestamp: 2024-06-10 12:00:00 UTC β†’ 1718013600

The key is always being explicit about timezone. "June 10 at noon" is ambiguous. "June 10 at noon UTC" is not β€” it maps to exactly one Unix timestamp.


How timezone bugs actually happen

Bug 1: Storing local time as if it's UTC

A server in London stores 2024-03-31 01:30:00 in the database as a timestamp. But on March 31, the UK clocks jump forward at 1:00 AM (BST begins). 1:30 AM doesn't exist in London on that date β€” the time jumps from 00:59 to 02:00.

If the application converts this time to a Unix timestamp without being explicit about the timezone, it might silently pick the wrong UTC offset and store a time that's off by an hour β€” or attempt to represent a time that never existed.

Fix: always store UTC in the database. Convert to local time only at display time.

Bug 2: The "midnight" assumption

A job is scheduled to run "at midnight every day." The server is in UTC. The developer wrote the schedule in their local timezone (UTC+2). The job runs at 10 PM UTC β€” which is "midnight" where the developer is, but 10 PM server time, which means it runs on a different day in UTC than intended.

The logs show: Job ran 2024-06-09 22:00:00 UTC. The developer says: "it ran at midnight June 10." Both are correct β€” in different timezones.

Fix: specify job schedules explicitly in UTC. Never use "midnight" without a timezone.

Bug 3: Daylight saving time gaps and doubles

In regions observing DST, one night per year has an hour that doesn't exist (the spring-forward gap) and one night has an hour that occurs twice (the autumn-fall-back overlap).

Spring forward: clocks jump from 01:59 to 03:00. There is no 02:30 that night. A system that tries to schedule something at 02:30 on that date either fails, silently picks the wrong time, or runs an hour late.

Fall back: clocks go from 01:59 back to 01:00. The hour 01:00–01:59 occurs twice. A timestamp of 01:30 on that date is ambiguous β€” is it the first 01:30 or the second? Unix timestamps are unambiguous: the two 01:30s are different Unix timestamps.

Fix: use Unix timestamps for all internal storage and computation. Convert to local time only for display.

Bug 4: JavaScript's millisecond timestamps

JavaScript's Date.now() and new Date().getTime() return milliseconds since epoch, not seconds. Most other languages and systems use seconds. Mixing them up produces dates in the year 53,000 or in 1970, depending on which direction the confusion goes.

1718000000 β†’ correct Unix timestamp β†’ June 2024 1718000000000 β†’ millisecond timestamp β†’ same date in JavaScript's Date object 1718000000000 interpreted as seconds β†’ year 56,430 (not what you wanted)

Fix: always document and check the unit. When receiving a timestamp from an external source, verify whether it's seconds or milliseconds before processing.


Converting timestamps in different languages

JavaScript:

// Unix seconds to Date
const date = new Date(1718000000 * 1000); // multiply by 1000 for ms

// Date to Unix seconds
const timestamp = Math.floor(Date.now() / 1000);

// ISO string to Unix
const ts = Math.floor(new Date('2024-06-10T08:53:20Z').getTime() / 1000);

Python:

from datetime import datetime, timezone

# Unix seconds to UTC datetime
dt = datetime.fromtimestamp(1718000000, tz=timezone.utc)

# UTC datetime to Unix seconds
ts = int(datetime(2024, 6, 10, 8, 53, 20, tzinfo=timezone.utc).timestamp())

# Current Unix timestamp
import time
ts = int(time.time())

SQL (PostgreSQL):

-- Unix seconds to timestamp
SELECT to_timestamp(1718000000);

-- Timestamp to Unix seconds
SELECT EXTRACT(EPOCH FROM '2024-06-10 08:53:20+00'::timestamptz);

Practical timestamp arithmetic

How long ago was an event?

Current time: 1718100000
Event time:   1718000000
Difference:   100000 seconds = 27.78 hours = 1 day, 3 hours, 46 minutes, 40 seconds

Because timestamps are just integers, arithmetic is trivial. No month-length confusion, no DST adjustments needed for duration calculations.

Is a token expired?

const isExpired = tokenExpiry < Math.floor(Date.now() / 1000);

JWT expiry (exp claim) is stored as a Unix timestamp in seconds. Comparing two timestamps is a simple integer comparison.

Scheduling relative times

"Run this 24 hours from now":

import time
run_at = int(time.time()) + (24 * 60 * 60)  # 86400 seconds

No datetime manipulation, no timezone conversion. 86,400 seconds is always exactly 24 hours, regardless of DST.


Using the Timestamp Converter on sadiqbd.com

  1. Paste a Unix timestamp β€” the converter shows the corresponding UTC date and your local time
  2. Enter a date and time β€” specify the timezone explicitly, get the Unix timestamp
  3. Check both seconds and milliseconds β€” the converter handles both and labels them clearly

Useful debugging scenarios:

  • A JWT exp field shows 1718003600 β€” paste it in to see exactly when it expires
  • A database record has created_at: 1700000000 β€” convert to see the human date
  • You need to query records from the last 30 days β€” calculate now - 2592000 (30 Γ— 86400)

Frequently Asked Questions

Should I store timestamps in the database as integers or as datetime types? Both work, but datetime types with explicit timezone (like PostgreSQL's TIMESTAMPTZ) are generally preferred β€” they enforce timezone awareness and integrate better with date arithmetic in SQL. Storing as Unix integer is portable but loses timezone metadata. Whichever you choose, always store UTC and never store local time without the offset.

What's the maximum Unix timestamp? On 32-bit systems, Unix timestamps overflow at 2147483647 β€” January 19, 2038 at 03:14:07 UTC. This is the "Year 2038 problem." 64-bit systems don't have this issue in any practical timeframe.

Why does my timestamp appear to be in the wrong timezone? Because timestamps have no timezone β€” the timezone interpretation happens at display time. If a timestamp is displayed in the wrong timezone, the display logic is using the wrong offset, not the timestamp itself.

Is the Timestamp Converter free? Yes β€” completely free, no sign-up required.


Timestamps are simple once you commit to one rule: store UTC, convert at display. The converter makes the back-and-forth between Unix seconds and human-readable dates instant β€” and understanding the underlying mechanics means timezone bugs become diagnosable rather than mysterious.

Try the Timestamp Converter free at sadiqbd.com β€” convert any Unix timestamp to a date, or any date to a timestamp, instantly.

Share:
Try the related tool:
Open Timestamp Converter

More Timestamp Converter articles