Convert Unix Timestamp in PostgreSQL
PostgreSQL provides built-in functions for Unix timestamp conversion. Use to_timestamp() to convert from epoch and EXTRACT(EPOCH FROM ...) to convert to epoch.
Unix Timestamp to Timestamp
-- From seconds (standard Unix timestamp) SELECT to_timestamp(1704067200); -- Result: 2024-01-01 00:00:00+00 -- From milliseconds (divide by 1000) SELECT to_timestamp(1704067200000 / 1000.0); -- Result: 2024-01-01 00:00:00+00 -- With fractional seconds SELECT to_timestamp(1704067200.5); -- Result: 2024-01-01 00:00:00.5+00 -- Cast to date only SELECT to_timestamp(1704067200)::date; -- Result: 2024-01-01
Timestamp to Unix Timestamp
-- Current timestamp in seconds SELECT EXTRACT(EPOCH FROM NOW()); -- Result: 1704067200.123456 -- Current timestamp as integer SELECT FLOOR(EXTRACT(EPOCH FROM NOW()))::bigint; -- Result: 1704067200 -- From specific timestamp SELECT EXTRACT(EPOCH FROM TIMESTAMP '2024-01-01 00:00:00 UTC'); -- Result: 1704067200 -- From timestamptz SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '2024-01-01 00:00:00+00'); -- Result: 1704067200 -- To milliseconds SELECT (EXTRACT(EPOCH FROM NOW()) * 1000)::bigint; -- Result: 1704067200000
Timezone Handling
-- to_timestamp returns timestamptz (timezone-aware)
SELECT to_timestamp(1704067200);
-- Result: 2024-01-01 00:00:00+00 (UTC)
-- Display in specific timezone
SELECT to_timestamp(1704067200) AT TIME ZONE 'America/New_York';
-- Result: 2023-12-31 19:00:00
SELECT to_timestamp(1704067200) AT TIME ZONE 'Asia/Tokyo';
-- Result: 2024-01-01 09:00:00
-- Convert between timezones
SELECT
TIMESTAMP '2024-01-01 00:00:00' AT TIME ZONE 'UTC'
AT TIME ZONE 'America/Los_Angeles';
-- Result: 2023-12-31 16:00:00
-- Set session timezone
SET timezone = 'America/New_York';
SELECT to_timestamp(1704067200);
-- Result: 2023-12-31 19:00:00-05Formatting
-- Various formats using to_char SELECT to_char(to_timestamp(1704067200), 'YYYY-MM-DD'); -- Result: 2024-01-01 SELECT to_char(to_timestamp(1704067200), 'Month DD, YYYY'); -- Result: January 01, 2024 SELECT to_char(to_timestamp(1704067200), 'FMMonth DD, YYYY'); -- Result: January 1, 2024 (FM removes padding) SELECT to_char(to_timestamp(1704067200), 'YYYY-MM-DD HH24:MI:SS'); -- Result: 2024-01-01 00:00:00 SELECT to_char(to_timestamp(1704067200), 'Day, DD Mon YYYY HH12:MI AM'); -- Result: Monday , 01 Jan 2024 12:00 AM -- ISO 8601 format SELECT to_char(to_timestamp(1704067200), 'YYYY-MM-DD"T"HH24:MI:SS"Z"'); -- Result: 2024-01-01T00:00:00Z
Practical Examples
-- Store Unix timestamp, query as date
CREATE TABLE events (
id SERIAL PRIMARY KEY,
name TEXT,
created_at BIGINT -- Unix timestamp in seconds
);
-- Insert with current timestamp
INSERT INTO events (name, created_at)
VALUES ('Event', EXTRACT(EPOCH FROM NOW())::bigint);
-- Query with human-readable date
SELECT
name,
to_timestamp(created_at) AS created_date
FROM events;
-- Filter by date range using epoch
SELECT * FROM events
WHERE created_at >= EXTRACT(EPOCH FROM '2024-01-01'::timestamptz)
AND created_at < EXTRACT(EPOCH FROM '2024-02-01'::timestamptz);
-- Better: Use timestamptz column directly
CREATE TABLE events_better (
id SERIAL PRIMARY KEY,
name TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);Common Pitfalls
TIMESTAMP vs TIMESTAMPTZ
TIMESTAMP ignores timezone context. Always use TIMESTAMPTZ when working with Unix timestamps.
-- ❌ Wrong - TIMESTAMP loses timezone info SELECT EXTRACT(EPOCH FROM TIMESTAMP '2024-01-01 00:00:00'); -- May give unexpected results depending on server timezone -- ✅ Correct - TIMESTAMPTZ is explicit SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '2024-01-01 00:00:00 UTC'); -- Always 1704067200
Milliseconds vs Seconds
PostgreSQL expects seconds. Passing milliseconds gives dates far in the future.
-- ❌ Wrong - milliseconds treated as seconds SELECT to_timestamp(1704067200000); -- Result: 55963-09-25 (way off!) -- ✅ Correct - divide by 1000 SELECT to_timestamp(1704067200000 / 1000.0); -- Result: 2024-01-01 00:00:00+00
Integer Division
When dividing milliseconds, use 1000.0 (float) to preserve precision. Integer division truncates fractional seconds.
Edge Cases
-- Negative timestamps (before 1970) SELECT to_timestamp(-86400); -- Result: 1969-12-31 00:00:00+00 -- Very old dates SELECT to_timestamp(-2208988800); -- Result: 1900-01-01 00:00:00+00 -- Far future SELECT to_timestamp(4102444800); -- Result: 2100-01-01 00:00:00+00 -- Sub-second precision SELECT to_timestamp(1704067200.123456); -- Result: 2024-01-01 00:00:00.123456+00 -- Epoch (the beginning) SELECT to_timestamp(0); -- Result: 1970-01-01 00:00:00+00
Frequently Asked Questions
What function converts Unix timestamps to dates in PostgreSQL?
Use to_timestamp(unix_seconds) to convert a Unix timestamp to a timestamp with time zone. For the reverse, use EXTRACT(EPOCH FROM timestamp).
Does PostgreSQL use seconds or milliseconds for epoch?
PostgreSQL uses seconds with decimal precision. If you have milliseconds, divide by 1000.0 before passing to to_timestamp().
What is the difference between TIMESTAMP and TIMESTAMPTZ?
TIMESTAMP stores date/time without timezone. TIMESTAMPTZ stores date/time with timezone awareness. Always use TIMESTAMPTZ for Unix timestamp conversions.
How do I get the current Unix timestamp in PostgreSQL?
Use EXTRACT(EPOCH FROM NOW()) or EXTRACT(EPOCH FROM CURRENT_TIMESTAMP). Both return the current time as a Unix timestamp.