Transforming an epoch-based integer or floating-point value into PostgreSQL’s DATE, TIMESTAMP, or TIMESTAMPTZ data types with built-in functions such as to_timestamp() and AT TIME ZONE.
A Unix timestamp (also called epoch time) represents the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970. PostgreSQL, however, stores calendar dates and times in rich, strongly-typed columns such as DATE
, TIMESTAMP
, and TIMESTAMPTZ
. Converting between these formats is a common task in data engineering pipelines, application back-ends, and ad-hoc analytics.
TIMESTAMPTZ
makes offsets explicit, reducing logic errors.date_trunc
, extract
) only works on timestamp types.An epoch value is usually a 32-bit or 64-bit integer counting seconds (or sometimes milliseconds) from the epoch. Because it is relative, it has no intrinsic time-zone metadata; you must know whether the source system recorded it as UTC or local time.
DATE
– calendar date with no time component.TIMESTAMP
– date + time without offset; interpreted in the session’s current time zone.TIMESTAMPTZ
– date + time + time-zone offset; stored internally in UTC.to_timestamp()
SELECT to_timestamp(1685577600);
-- returns 2023-06-01 00:00:00+00
to_timestamp()
expects epoch seconds (or double precision seconds). The default result is a TIMESTAMPTZ
in the session’s time zone.
AT TIME ZONE
SELECT to_timestamp(1685577600) AT TIME ZONE 'America/Los_Angeles';
-- 2023-05-31 17:00:00
AT TIME ZONE
converts a TIMESTAMPTZ
to a plain TIMESTAMP
relative to the specified zone.
SELECT to_timestamp(epoch_millis / 1000.0);
Be sure to divide by 1000.0
so PostgreSQL treats the value as double precision
. A common alternative is using integer division and then adding make_interval()
, but floating-point is simpler and performant for most use cases.
DATE
SELECT to_timestamp(1685577600)::date;
-- 2023-06-01
Once you have a TIMESTAMP
, you can cast directly to DATE
if you only need the calendar day.
UPDATE
ALTER TABLE events ADD COLUMN event_ts TIMESTAMPTZ;
UPDATE events
SET event_ts = to_timestamp(epoch_seconds)
WHERE event_ts IS NULL;
SELECT *
FROM page_views
WHERE view_time > to_timestamp($1) -- $1 passed in as epoch seconds
AND user_id = $2;
TIMESTAMPTZ
over TIMESTAMP
for long-term storage.TIMESTAMPTZ
using B-tree or BRIN indexes perform far better than on raw integers.Why it’s wrong: Passing milliseconds directly to to_timestamp()
inflates the result by 1,000×.
Fix: Divide by 1000.0
or use integer arithmetic (epoch_ms / 1000
).
Why it’s wrong: to_timestamp()
returns a timestamp in the current session zone, leading to inconsistent results across connections.
Fix: Immediately chain AT TIME ZONE 'UTC'
(or your canonical zone) after to_timestamp()
, or set SET TIME ZONE 'UTC'
at the start of the session.
TIMESTAMP
Without OffsetWhy it’s wrong: Dropping the offset makes daylight-saving conversions and cross-region analytics error-prone.
Fix: Use TIMESTAMPTZ
or keep the raw epoch and convert on read.
If you are using the Galaxy SQL editor, converting Unix timestamps is even easier:
to_timestamp(
and Galaxy’s AI copilot autocompletes the signature and warns if you feed it milliseconds.to_timestamp()
and safe casting.Unix timestamps are ubiquitous in log files and APIs, but PostgreSQL’s rich time types unlock advanced querying, easier debugging, and better performance. By mastering to_timestamp()
, AT TIME ZONE
, and careful time-zone management, you can move seamlessly between raw epoch data and business-friendly dates.
Many data sources emit time as raw epoch integers. Converting them to PostgreSQL’s native timestamp types enables indexing, time-zone safety, and powerful date functions. Without proper conversion, analytics pipelines, monitoring dashboards, and application logic suffer from off-by-hours errors and slow queries.
Divide the millisecond integer by 1000.0
to get seconds as a double, then call to_timestamp()
: to_timestamp(epoch_ms/1000.0)
.
It returns TIMESTAMP WITH TIME ZONE
(TIMESTAMPTZ
) in the session’s current zone. Use AT TIME ZONE
to convert it to another zone or strip the offset.
Your session or the AT TIME ZONE
clause is applying DST rules. Store data in UTC (to_timestamp(epoch) AT TIME ZONE 'UTC'
) and apply presentation-layer offsets later.
Galaxy’s AI copilot autocompletes to_timestamp()
, checks for millisecond precision, and offers one-click refactors. You can save the final query in a Collection so teammates reuse the correct pattern.