Home Linux AdministrationUnix Timestamps: A Practical Guide for Developers

Unix Timestamps: A Practical Guide for Developers

A Beginners Guide to Unix Timestamps: Convert Timestamps, Understand Units and Time Zones, and Avoid Precision, Leap-second, and Year 2038 Bugs.

By sk
1 views 28 mins read

A Unix timestamp looks like a number. That is the beauty of it, and also the source of many bugs.

You can store it in a database, send it over a network, compare it with another timestamp, or use it to calculate how long something took. You do not need to agree on a date format or a time zone just to compare two ordinary timestamps.

But there is a catch: a timestamp represents time according to a convention. It does not guarantee that a clock is correct, that two events get different values, or that the number measures elapsed time reliably.

In this detailed guide, we will explain what a Unix timestamp is, and its usage with practical examples.

Table of Contents

1. What exactly is a Unix timestamp?

The Unix epoch is the reference point at: 1970-01-01 00:00:00 UTC

The Unix Epoch: 1970-01-01 00:00:00 UTC

Unix TimestampMeaningUTC Date and Time
0Epoch itself1970-01-01 00:00:00 UTC
1One second after the epoch1970-01-01 00:00:01 UTC
-1One second before the epoch1969-12-31 23:59:59 UTC

A Unix timestamp, in the common seconds-based form, is the number of seconds counted from this reference point, using the Unix/POSIX time convention. A negative value represents a time before the epoch on systems that support it.

The Open Group describes this as a value that approximates the number of seconds since the epoch, an important word we will return to later.

For example:

Unix timestampUTC date and time
01970-01-01 00:00:00
11970-01-01 00:00:01
601970-01-01 00:01:00
864001970-01-02 00:00:00
-11969-12-31 23:59:59
14832288002017-01-01 00:00:00

Notice that 86400 represents the next calendar day. In the ordinary Unix time model, a day has 86,400 seconds. Leap seconds are where that simple model stops matching UTC perfectly.

Please remember that Unix time originated with Unix, but you do not need to run Unix to use it. Linux, macOS, Windows APIs, browsers, databases, and distributed systems all have their own ways to represent time, many of which use the same epoch.

2. Seconds, Milliseconds, Microseconds and Nanoseconds

The first thing to get right when reading a timestamp is its unit.

A Unix timestamp does not inherently tell you whether the number means seconds, milliseconds, or something smaller. The surrounding API or data format defines the unit.

UnitOne unit equalsTypical use
Seconds (s)1 secondUnix timestamps, APIs, shell tools
Milliseconds (ms)0.001 secondsJavaScript, many application APIs
Microseconds (µs)0.000001 secondsDatabase timestamps, performance data
Nanoseconds (ns)0.000000001 secondsSystems programming, high-resolution timing

At the time of writing this guide, a timestamp for a date in 2026 has roughly these values, depending on the unit:

UnitApproximate number
Seconds1,798,000,000
Milliseconds1,798,000,000,000
Microseconds1,798,000,000,000,000
Nanoseconds1,798,000,000,000,000,000

These are illustrative values, not a particular instant.

Please note that changing the unit changes the number dramatically, but it does not change the underlying point in time.

The Classic Bug: Seconds versus Milliseconds

Suppose an API returns this:

{
"created_at": 1483228800
}

That represents 2017-01-01 00:00:00 UTC if the API defines the field as Unix seconds.

Now consider JavaScript:

const timestamp = 1483228800;

console.log(new Date(timestamp).toISOString());

You will get a date in January 1970, not 2017.

Why? JavaScript's Date constructor expects milliseconds, not Unix seconds. That behavior is documented by MDN.

Convert the unit first:

const timestampSeconds = 1483228800;

const date = new Date(timestampSeconds * 1000);

console.log(date.toISOString());
// 2017-01-01T00:00:00.000Z

To get the current Unix timestamp in seconds:

const nowSeconds = Math.floor(Date.now() / 1000);

To get it in milliseconds:

const nowMilliseconds = Date.now();

Both are valid. The mistake is using one where the other is expected.

Important: Never guess a timestamp's unit from its number of digits. Document the unit in your API contract, database schema, and variable names.

Prefer names such as created_at_ms, epoch_seconds, or timestamp_ns over a vague name such as time.

3. Convert Unix Timestamps from the Command Line

You do not need a programming language to inspect timestamps. The Unix command line has always been a good place to learn how time works.

The following first set of examples uses GNU date, commonly found on Linux. GNU documents these conversions in its Coreutils manual.

Get the Current Unix timestamp

date +%s

Sample Output:

1792589190

The output changes every second. Your actual value will depend on when you run the command.

Convert a Timestamp to a Readable Date

date -u -d '@1483228800' '+%Y-%m-%dT%H:%M:%SZ'

Sample Output:

2017-01-01T00:00:00Z

Here is what the options mean:

  • -u asks date to use UTC.
  • -d tells GNU date which date or timestamp to parse.
  • @1483228800 means a Unix-style timestamp.
  • +%Y-%m-%dT%H:%M:%SZ specifies the output format.

The @ before the number matters to GNU date: it tells the command to interpret that number as a timestamp, rather than as an ordinary date string.

Convert a Date into a Timestamp

Run:

date -u -d '2017-01-01 00:00:00' +%s

Sample Output:

1483228800

You can use this in scripts, log investigations, and debugging sessions.

Display Fractional seconds

GNU date also supports nanosecond formatting:

date +'%Y-%m-%dT%H:%M:%S.%N%:z'

Sample Output:

2026-10-21T18:59:21.575616862+05:30

That output illustrates nanosecond formatting. It does not mean the clock is accurate to a nanosecond. The clock's real resolution and accuracy depend on the system.

For a quick look at the reported resolution:

date --resolution

These particular options are GNU extensions. macOS and some BSD systems have different date syntax. On macOS, for example, you can convert a timestamp with:

date -u -r 1483228800 '+%Y-%m-%dT%H:%M:%SZ'

When a command behaves differently across machines, check which implementation you are using before blaming the timestamp.


Recommended Read:


4. Time Zones Do Not Change the Timestamp

This is one of the most useful things to understand.

A Unix timestamp does not contain a time zone. It represents a point in time according to the Unix time convention.

The same instant can have different human-readable representations.

For example, the instant represented by 1483228800 is:

Time zoneDisplayed time
UTC2017-01-01 00:00:00
India (Asia/Kolkata)2017-01-01 05:30:00
New York2016-12-31 19:00:00

The instant is the same. Only its representation changes.

You can verify the India example on Linux:

TZ=Asia/Kolkata date -d '@1483228800'

Then compare it with UTC:

TZ=UTC date -d '@1483228800'

The number stays the same.

Why this matters

Imagine you are investigating an incident and your server logs say:

Request received: 1790000000

A colleague in another country asks what time that was.

If you convert the number using your machine's local time zone, you may give the colleague a different displayed time than they expect. Neither clock necessarily disagrees about the instant; you have simply used different time zones.

For logs, APIs, and distributed systems, UTC is usually the easiest common representation. For human-facing output, convert to the user's relevant time zone.

Note: a time zone is not just a fixed UTC offset. Many places change their clocks according to daylight-saving rules, and governments can change those rules. Libraries such as Python's zoneinfo use time-zone database information to handle those changes.

So when you need to schedule something in a place, a name such as America/New_York is often more useful than just -05:00.

5. UTC, Unix time, TAI and Leap Seconds

Now we reach the interesting part.

People often say "Unix time is UTC." That is a convenient shorthand, but it hides an important distinction.

UTC is a time scale. Unix time is a way of representing time using an epoch-based counting convention. They are closely related, but they do not behave identically around leap seconds.

Let's separate the main concepts.

TermWhat it means
UTCThe international reference time scale used for civil time
Unix epochThe reference point at 1970-01-01 00:00:00 UTC
Unix/POSIX timeAn epoch-based numerical representation that normally ignores leap seconds
TAIInternational Atomic Time, a continuous atomic time scale
UT1A time scale based on Earth's rotation

UTC is kept close to Earth's rotational time, UT1, by applying leap seconds under the traditional rules. TAI, by contrast, advances continuously without UTC's leap-second adjustments. The Bureau International des Poids et Mesures (BIPM) explains the relationship in its UTC resolutions.

Why not just let all clocks run according to atomic time?

Because people care about Earth's rotation. Noon has traditionally meant something close to when the Sun is highest in the sky. Atomic clocks are much more regular than Earth's rotation, so UTC historically used occasional one-second adjustments to keep the two reasonably aligned.

That is where leap seconds enter the picture.

The 2016 Leap Second

On 31 December 2016, UTC included the following sequence:

23:59:58
23:59:59
23:59:60 <- leap second
00:00:00
00:00:01

In the above output, the middle 23:59:60 is real. It is not a typo. RFC 3339, a standard for Internet date-time representations, explicitly allows second 60 when the applicable leap-second rules permit it.

But the ordinary Unix time representation does not provide a portable, distinct integer timestamp for that inserted second.

On typical POSIX systems, the values around the boundary look like this:

UTC clock readingConventional Unix timestamp
2016-12-31 23:59:581483228798
2016-12-31 23:59:591483228799
2016-12-31 23:59:60No separate, portable Unix timestamp
2017-01-01 00:00:001483228800
2017-01-01 00:00:011483228801

This is the essential point: the usual Unix mapping cannot uniquely represent every UTC clock reading during a leap second.

The qualification is that the exact behavior depends on the clock implementation and its leap-second handling. A machine might repeat a second, step its clock, or smear the leap second across a longer interval. Linux's CLOCK_REALTIME, for example, normally ignores leap seconds and may be adjusted by NTP around a leap second.

So Unix timestamps are unique 99.9999% of the time. I would say:

Unix timestamps represent instants according to a convention, but they are not guaranteed to be unique identifiers for events, and leap seconds expose a mismatch between this convention and UTC.

That statement remains useful even after leap seconds stop being inserted.

An Important Current Development: UTC is Changing

As of 21 October 2026, this is no longer merely a future proposal.

The General Conference on Weights and Measures adopted Resolution 5 in 2026, which states that continuous UTC will take effect on 20 May 2027. It also sets a maximum permitted difference of one hour between UTC and UT1. The decision aims to end leap-second adjustments and avoid their risks to critical digital infrastructure.

Why was this change made?

The 2022 resolution had already recognized that leap seconds can cause serious malfunctions in digital infrastructure. The first negative leap second, removing a second rather than adding one, had never been implemented, and the relevant software systems were not broadly prepared for it.

The 2026 decision brings the transition forward. The new rules do not change the Unix epoch or magically make historical Unix timestamps leap-second-aware. They change how UTC will remain aligned with Earth's rotation in the future.

For everyday developers, the sensible response is still to use standard timestamp APIs, keep clocks synchronized, and avoid assuming that a wall clock is a perfect counter of elapsed seconds.

6. Precision is Not Accuracy

This is another trap.

Suppose you record the current time as:

1790000000.123456789

You have nine digits after the decimal point. That gives you a representation with nanosecond precision.

But that says nothing by itself about the accuracy of the clock.

Consider three separate concepts:

ConceptQuestion it answers
PrecisionHow finely can the value be represented?
ResolutionWhat is the smallest difference the clock can report?
AccuracyHow close is the reported time to the intended reference time?

You could have a clock that reports nanoseconds but is 200 milliseconds behind UTC. It has a fine-grained representation and poor absolute accuracy.

Likewise, two calls to a clock API may return the same value because the clock's resolution is limited, even if the calls occurred at different times. Python explicitly notes that successive calls to datetime.now() can return the same instant, depending on the underlying clock's precision.

This distinction matters for databases, profiling, telemetry, and distributed systems.

A field with nine decimal places is not proof that nine decimal places carry meaningful information.

7. Wall-clock Time versus Monotonic Time

This distinction has saved many production systems from subtle bugs.

A Unix timestamp normally comes from a wall clock: a clock intended to tell you the current date and time.

On Linux, CLOCK_REALTIME provides this kind of time. But the system clock can be adjusted. An administrator can change it, and NTP synchronization can change its rate or step it forward or backward.

Imagine you measure a request like this:

Start time:  10:00:05
End time: 10:00:03

Did the request take negative two seconds?

Of course not. The clock moved backward between your two readings.

This is why operating systems provide monotonic clocks.

A monotonic clock gives you a value that does not go backward. Its origin is not the Unix epoch; it is an implementation-defined reference point, often related to system uptime on Linux.

That makes it unsuitable for a normal calendar timestamp, but excellent for measuring durations.

TaskAppropriate kind of clock
Record when a user signed inWall clock / Unix timestamp
Store when a database row was createdWall clock / database timestamp
Measure how long a function takesMonotonic clock
Implement a timeoutMonotonic clock
Schedule a report for a specific dateWall-clock time with calendar and time-zone rules

On Linux, CLOCK_MONOTONIC is not affected by discontinuous wall-clock jumps, although its rate can still be adjusted. Other clock variants have different semantics; for example, CLOCK_BOOTTIME also counts time spent in system suspend.

You can read more in the clock_getres(2) manual page.

A Practical Rule

Do not measure elapsed time by subtracting two ordinary Unix timestamps when you can use a monotonic clock.

The timestamp tells you when the system thinks something happened. The monotonic clock helps you tell how much time passed between two operations.

Those are different jobs.

8. Practical Examples in Python, JavaScript and SQL

The principles become clearer when you use them in code.

Python

Convert a timestamp into a UTC datetime:

from datetime import datetime, timezone

timestamp = 1483228800

dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
print(dt.isoformat())

Sample Output:

2017-01-01T00:00:00+00:00

Convert a timezone-aware datetime back into a timestamp:

from datetime import datetime, timezone

dt = datetime(2017, 1, 1, 0, 0, 0, tzinfo=timezone.utc)

print(int(dt.timestamp()))

Sample Output:

1483228800

Pay attention to timezone.utc. A naive Python datetime does not tell Python which time zone it represents. If your program treats a naive datetime as UTC while a library interprets it as local time, you can introduce an offset error.

Python recommends aware UTC datetimes for representing specific moments in time. Its datetime module also does not support leap seconds in the ordinary datetime model.

To get the current Unix time in different units:

import time

seconds = time.time()
milliseconds = time.time_ns() // 1_000_000
nanoseconds = time.time_ns()

Use integer nanoseconds when you need to preserve the underlying API's timestamp value without first converting it to a floating-point number.

For elapsed time, use:

import time

start = time.monotonic_ns()

# Do some work here.

elapsed_ns = time.monotonic_ns() - start
elapsed_seconds = elapsed_ns / 1_000_000_000

print(f"Elapsed: {elapsed_seconds:.6f} seconds")

The _ns suffix tells you the unit. It does not promise that the clock itself measures time with one-nanosecond accuracy.

JavaScript

The Date API uses milliseconds since the Unix epoch.

const timestampSeconds = 1483228800;

const date = new Date(timestampSeconds * 1000);

console.log(date.toISOString());
// 2017-01-01T00:00:00.000Z

If your API provides Unix seconds, multiply by 1000 before constructing the Date.

If you want to convert Date.now() to Unix seconds:

const timestampSeconds = Math.floor(Date.now() / 1000);

For dates before or after the epoch, JavaScript's date values can also represent negative timestamps. The normal Date representation uses milliseconds, not nanoseconds; if you need to handle current epoch nanoseconds, the number is too large for JavaScript's Number type to represent every integer exactly. Use BigInt or an appropriate high-resolution time API for such values.


Recommended Read:


PostgreSQL

PostgreSQL can convert between epoch seconds and timestamp values:

SELECT to_timestamp(1483228800);

This returns the corresponding timestamp with time zone. Its displayed offset depends on the PostgreSQL session's configured time zone.

The reverse conversion is:

SELECT EXTRACT(
EPOCH FROM TIMESTAMPTZ '2017-01-01 00:00:00+00'
);

Result:

1483228800.000000

PostgreSQL documents to_timestamp() and EXTRACT(EPOCH ...) in its date/time functions.

One common database mistake is confusing timestamp without time zone with timestamp with time zone (timestamptz in PostgreSQL). A timestamp without a time zone does not unambiguously identify an instant. PostgreSQL stores timezone-aware timestamps internally in UTC and renders them according to the session's time-zone setting.

For events that happened at a particular instant, use an unambiguous time representation. If you need to preserve the original time-zone name or user-entered local time, store that information separately.

9. Can a Unix Timestamp be Used as a Database Primary Key?

Suppose you create a table like this:

CREATE TABLE events (
id BIGINT PRIMARY KEY,
event_name TEXT NOT NULL
);

And you decide that id will hold the current Unix timestamp.

That can work in a very low-volume system if you use seconds and guarantee at most one insert per second. But the moment you have concurrent users, two events may happen during the same second. Both try to insert the same primary key, and one insert fails.

You might improve things by using milliseconds or nanoseconds. That reduces collision risk due to limited resolution, but it does not guarantee uniqueness.

There are several reasons:

  • Two operations can occur within the same clock resolution.
  • A clock can repeat a value after a correction or a leap-second handling event.
  • Two different servers can report the same time.
  • Two servers can have clocks that disagree.
  • A system clock can be adjusted backward, so a later operation can receive a smaller timestamp.

A timestamp is excellent metadata for when. It is not a reliable identifier for which.

What Should You Use Instead?

For ordinary database identity, use a database-generated sequence or a suitable unique identifier such as a UUID.

If you need to preserve the event time as well, store both:

CREATE TABLE events (
id UUID PRIMARY KEY,
occurred_at TIMESTAMPTZ NOT NULL,
event_name TEXT NOT NULL
);

Now id identifies the event, while occurred_at records when it happened.

If you need a strict event order, particularly across multiple services, timestamps alone still may not be enough. A database sequence, a log offset, or a distributed ordering mechanism may be more appropriate, depending on the system.

10. The Year 2038 problem

The Unix epoch has another famous edge case: the Year 2038 problem.

Some old systems stored seconds since the epoch as a signed 32-bit integer.

The largest signed 32-bit integer is:

2147483647

Interpreted as Unix seconds, it represents:

2038-01-19 03:14:07 UTC

One second later, the count exceeds that integer's range. A program that depends on that representation can overflow or otherwise fail.

The same signed 32-bit representation cannot express dates earlier than 1901-12-13 20:45:52 UTC in this encoding. GNU documents this range and the wider range available on modern 64-bit systems.

Modern systems generally use wider timestamp representations, but do not assume every application, file format, embedded device, database driver, or network protocol has been updated.

For long-lived systems, check the actual integer type, serialization format, and API range. Simply upgrading a server does not automatically fix an old 32-bit timestamp stored in a file or database.

11. Date Strings, Timestamps and Future Schedules

A final point deserves special attention: not every time-related problem should be solved using a Unix timestamp.

A timestamp is good for representing a particular instant.

But consider these requests:

  • Send a report at 9:00 AM tomorrow.
  • Run a task every day at 2:00 AM.
  • Schedule a meeting for 9:00 AM on the first Monday of each month.
  • Remind me every weekday at 8:30 AM in India.

These are calendar rules. They need a date, a local clock time, a time zone, and sometimes a recurrence rule.

Suppose a user schedules a meeting for 9:00 AM in New York next March. If you store only one timestamp, you preserve the calculated instant, but not necessarily the user's original scheduling intent. If time-zone rules change before then, the intended local time and the previously calculated instant may no longer match.

For a future recurring schedule, store the local time and the relevant time-zone identifier, such as America/New_York, alongside the recurrence rule. Resolve each occurrence using current time-zone rules.

For an event that has already happened, storing the event instant in UTC is generally straightforward.

Prefer an Unambiguous Text Format

A good Internet timestamp format is:

2026-10-20T10:15:10Z

The Z indicates UTC.

A time with an explicit offset is also unambiguous:

2026-10-20T10:15:10+05:30

These two examples represent different instants, since one has a UTC offset of zero and the other is five hours and thirty minutes ahead of UTC.

RFC 3339 defines a standardized Internet date-time format intended to reduce confusion between different representations.

Avoid sending a bare date-time such as 2026-10-20 10:15:10 across a system boundary unless you have explicitly defined which time zone it represents.

12. A Practical Checklist for Production Systems

When you design an application that records or calculates time, these habits will prevent many common bugs.

Use a documented unit. State whether every timestamp is in seconds, milliseconds, microseconds, or nanoseconds. Do not rely on digit counts.

Use UTC for event instants. Store and transmit a consistent representation, then convert to local time for display.

Use appropriate time types. In a database, prefer a timestamp type with clear time-zone semantics rather than an ambiguous local date-time. For recurring schedules, preserve the local time and the time-zone rules that define the schedule.

Use a monotonic clock for durations. Timeouts, benchmarks, and performance measurements should not depend on wall-clock adjustments.

Do not treat time as an ID. Use a sequence or unique identifier for identity, and use the timestamp for event time.

Know your clock's limits. Nanosecond formatting does not imply nanosecond accuracy. A wall clock can move backward. Different machines can disagree about the current time.

Test boundaries. Check timestamp unit conversions, pre-epoch dates, 32-bit limits, daylight-saving transitions, and how your system handles clock synchronization. Systems that need strict timekeeping should also test the leap-second behavior of their actual clock and runtime environment.

Keep formats and semantics separate. A number such as 1790000000 is not self-describing. A value such as 2026-10-20T10:15:10Z explicitly states a calendar representation and its UTC relationship.

Common Misconceptions about Unix Timestamps

The biggest mistake people make is treating a Unix timestamp as a perfect clock counter. It is a useful representation of time, but it does not guarantee that the clock is correct, that values are unique, or that time always moves forward.

Here are the most common misconceptions, why they are wrong, and what to do instead.

Misconception 1: Every Unix timestamp is unique

Wrong. A timestamp is not a unique identifier.

Suppose two requests arrive during the same second:

import time

request_a = int(time.time())
request_b = int(time.time())

print(request_a == request_b)
# True is entirely possible

Both requests can receive the same timestamp. This is normal, not a bug.

Using milliseconds or nanoseconds reduces the chance of collisions, but it does not guarantee uniqueness. Two machines can also generate the same timestamp independently.

Better approach: Use a UUID or database-generated ID to identify records. Store the timestamp separately to record when each event occurred.

Misconception 2: A Unix timestamp is simply UTC converted into a number.

Not quite. Unix time and UTC are closely related, but they are not identical concepts.

Unix timestamps conventionally count seconds from 1970-01-01 00:00:00 UTC. POSIX time does not represent leap seconds as separate, ordinary timestamp values. That creates a mismatch when UTC includes a second labelled 23:59:60. Different clock implementations can handle that boundary differently.

For example, during the leap second on 31 December 2016, UTC had these successive readings:

23:59:59
23:59:60 <- leap second
00:00:00

Ordinary Unix timestamps do not provide a portable, distinct integer for all three readings.

There is also an upcoming change. The international metrology body BIPM has decided that continuous UTC will take effect on 20 May 2027, removing the need for future leap-second adjustments under the new rules. Historical timestamps and existing software conventions will still matter.

Better approach: Treat Unix timestamps as a specific time representation, and check the time scale and leap-second behaviour when working with precision-sensitive systems.

Misconception 3: A Unix timestamp always moves forward.

Wrong. The system's wall clock can move backward.

A Unix timestamp usually comes from the system's real-time clock. That clock can be adjusted because it was wrong, because an administrator changed it, or because a time-synchronization service corrected it.

Imagine this sequence:

10:00:05  First reading
10:00:03 Second reading

The second reading is earlier even though you took it later. The clock may have been corrected between the two readings.

Linux documents this behaviour for CLOCK_REALTIME. It also provides CLOCK_MONOTONIC, whose readings do not go backward.

Better approach: Use wall-clock timestamps to record when events happened. Use a monotonic clock to measure durations and implement timeouts.

import time

start = time.monotonic()

# Perform some operation here.

elapsed = time.monotonic() - start
print(f"Took {elapsed:.3f} seconds")

Do not use time.time() as your stopwatch when a monotonic clock is available.

Misconception 4: A timestamp's number tells me its unit.

Wrong. Unix timestamps can use seconds, milliseconds, microseconds, or nanoseconds. The number alone does not define the unit.

The same instant might be represented as:

UnitExample value
Seconds1483228800
Milliseconds1483228800000
Microseconds1483228800000000
Nanoseconds1483228800000000000

Consider JavaScript:

new Date(1483228800);

This does not represent 1 January 2017. JavaScript's Date API interprets the number as milliseconds since the epoch, so the result falls in January 1970.

Use the correct unit:

new Date(1483228800 * 1000).toISOString();
// "2017-01-01T00:00:00.000Z"

Better approach: Document units explicitly. Name fields timestamp_seconds or created_at_ms, rather than simply timestamp.

Misconception 5: Nanosecond precision means nanosecond accuracy.

Wrong. Precision, resolution, and accuracy describe different things.

TermMeaning
PrecisionHow finely a value can be represented
ResolutionThe smallest difference a clock can report
AccuracyHow close the reported time is to the reference time

A clock might report:

10:15:10.123456789

That does not prove it knows the correct time to within one nanosecond. Its clock might be significantly out of sync with UTC.

Even two consecutive clock readings can return the same value when the clock's resolution is limited. Linux's clock documentation explicitly distinguishes the resolution of a clock from its returned time values.

Better approach: When timing or synchronization matters, examine the actual clock resolution, synchronization status, and error bounds. Don't assume that more decimal places mean better timekeeping.

Misconception 6: A Unix timestamp changes when the time zone changes.

Wrong. The timestamp does not contain a time zone.

The same timestamp can be displayed differently depending on the time zone you choose.

For example, timestamp 1483228800 represents the instant displayed as:

Time zoneLocal date and time
UTC2017-01-01 00:00:00
India2017-01-01 05:30:00
New York2016-12-31 19:00:00

The instant is the same. The displayed calendar time changes.

This is why the following commands can produce different dates or hours:

TZ=UTC date -d '@1483228800'
TZ=Asia/Kolkata date -d '@1483228800'

These examples use GNU date.

Better approach: Store unambiguous event times, use UTC as the common reference for logs and APIs, and convert to the appropriate local time zone for display. For future appointments, preserve the relevant time-zone rules, not just a calculated timestamp.

Misconception 7: Every day contains exactly 86,400 seconds.

Wrong. An ordinary Unix day is often treated as 86,400 seconds, but a local calendar day does not always have that duration.

Daylight-saving transitions can make a local day 23 or 25 hours long. Historically, UTC leap seconds have also introduced days containing an extra second.

For example, a daily job scheduled for 9:00 AM local time should not necessarily run by adding exactly 86,400 seconds to its previous execution time. Doing so can shift its local execution time across a daylight-saving transition.

Better approach: Use calendar-aware scheduling for recurring events. Use elapsed-time calculations for durations. They are different operations.

Misconception 8: Subtracting two timestamps always gives the true elapsed time.

Wrong. Subtraction gives you the difference between two recorded wall-clock readings, which may not equal the actual elapsed duration.

For example:

Start reading: 1000
End reading: 995

The difference is -5 seconds, but the operation did not run backward in time. The wall clock changed.

Even when the clock moves only forward, synchronization adjustments or differences between machines' clocks can make the calculated duration inaccurate.

Better approach: Use a monotonic clock when measuring execution time, latency, or timeouts. Use wall-clock timestamps when you need calendar dates and event times.

If you compare timestamps from two servers, remember that their clocks may not agree perfectly.

Misconception 9: Dates before 1970 cannot have Unix timestamps.

Wrong. Timestamps can be negative.

The Unix epoch is a reference point, not the beginning of time.

Unix timestampUTC date and time
-21969-12-31 23:59:58
-11969-12-31 23:59:59
01970-01-01 00:00:00
11970-01-01 00:00:01

A negative timestamp simply represents a time before the epoch.

However, supported date ranges depend on the programming language, operating system, database, and underlying data type.

Better approach: When dealing with historical dates, check the supported range of the complete system rather than assuming every timestamp must be positive.

Misconception 10: The Year 2038 problem affects every Unix timestamp.

Wrong. It affects systems that store Unix seconds in a signed 32-bit integer, not every system that uses Unix timestamps.

A signed 32-bit integer has a maximum value of 2147483647, corresponding to:

2038-01-19 03:14:07 UTC

One second later, that representation overflows. Software that relies on it can fail or produce incorrect dates.

Modern 64-bit systems commonly use wider time representations, but legacy software, embedded devices, file formats, or database fields can still have limits.

Better approach: Check the actual data type and serialization format. Do not assume that upgrading to a 64-bit operating system fixes timestamps already stored in a 32-bit format.

Misconception 11: A timestamp is enough to represent any date or time requirement.

Wrong. A timestamp works well for recording a particular instant, but some requirements describe calendar rules rather than instants.

Consider these two requirements:

  • “This payment happened at 9:00 AM.”
  • “Send a report at 9:00 AM every Monday in India.”

The first describes an event that occurred. The second describes a recurring schedule.

A single timestamp cannot fully describe a recurring schedule. You need the local time, time zone, and recurrence rule to preserve the intended behaviour.

Better approach: Use timestamps for event instants. Use calendar-aware date-time types and time-zone identifiers for future appointments and recurring schedules.

The Five Rules Worth Remembering

MisconceptionWhat to remember
Timestamps are uniqueUse IDs to identify records.
Unix time is exactly UTCLeap seconds expose differences between time scales.
Clocks only move forwardWall clocks can be adjusted backward.
More digits mean better accuracyPrecision does not guarantee accuracy.
Every time problem needs a timestampDurations and calendar schedules need different tools.

The underlying lesson is simple: a timestamp is a representation of time, not a guarantee about time. Once you understand that distinction, most Unix timestamp surprises become easier to explain and easier to prevent.


Suggested Read:


13. Summary

Let me summarize what we learned so far about Unix timestamps:

  • A Unix timestamp is a numerical representation of time relative to the Unix epoch.
  • A timestamp is not automatically a unique identifier.
  • The unit is part of the meaning of the number.
  • UTC, Unix time, atomic time, and a monotonic clock solve related but different problems.
  • A more precise representation does not automatically give you a more accurate clock.
  • Leap seconds reveal that calendar time and an ordinary Unix count are not perfectly interchangeable. Even with continuous UTC taking effect on 20 May 2027, these distinctions remain important.

Never use a number without knowing what that number means. This is especially true for time. The code may compile, the database may accept the value, and the API may return a perfectly valid integer. The bug often lies in the assumptions around it, not in the number itself.

Once you separate instants, calendar rules, durations, clock behavior, precision, and identity, Unix timestamps become much less mysterious, and a lot easier to use safely.

Resources:

You May Also Like

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies to improve your experience. By using this site, we will assume that you're OK with it. Accept Read More