HOWTO · PostgreSQL
How to Use UTC Current Time as Default in PostgreSQL
Learn how to get the current time in UTC and use it as a PostgreSQL column default.
On this page
To get the current time as a UTC clock reading in PostgreSQL, use now() AT TIME ZONE 'UTC'. To set a timestamp without time zone column to that reading when an insert omits the column, use the same expression as its DEFAULT. The value contains a date and clock time but no zone marker. If the column should represent an instant, use timestamp with time zone instead.
The SQL examples below are illustrative and were not run against a PostgreSQL server. The Python example provides a deterministic illustration of representing a UTC clock reading; it does not connect to PostgreSQL.
Get the Current Time in UTC in PostgreSQL
Run SELECT now() AT TIME ZONE 'UTC'; to obtain a UTC clock reading. PostgreSQL’s now() returns the start time of the current transaction, so repeated calls in one transaction return the same instant. The AT TIME ZONE operation converts that timestamp with time zone instant into a timestamp without time zone value whose date and clock fields show UTC. The result itself has no zone or offset attached.
By comparison, SELECT now(); returns a timestamp with time zone. PostgreSQL displays that instant using the session time zone, but the display does not change the instant. A timestamp without time zone stores only calendar and clock fields: it carries no time-zone or UTC-offset metadata and is not inherently UTC. Use it for UTC readings only when your application and database agree on that meaning.
Set a UTC Timestamp Default for a Table Column
For a column intended to hold UTC clock readings, define it as timestamp without time zone with DEFAULT (now() AT TIME ZONE 'UTC'). For example, the SQL expression is CREATE TABLE event_log (created_at timestamp without time zone DEFAULT (now() AT TIME ZONE 'UTC'), event_name text);. Parentheses around the default expression are optional.
Insert a row while omitting created_at, for example with INSERT INTO event_log (event_name) VALUES ('started');, and PostgreSQL evaluates the default for that column. An explicit value supplied for created_at takes precedence. A default is applied on insertion; it does not update the value automatically later. Because now() is fixed at transaction start, rows inserted in the same transaction receive the same timestamp. For event data that should represent an instant across clients, timestamp with time zone is generally the more suitable type; each session can display that instant in its own time zone.
Convert the Current Time to UTC
The equivalent function form is timezone('UTC', now()). PostgreSQL’s timezone() accepts a zone and a timestamp value; with now(), it returns a timestamp without time zone showing the instant in UTC. This is a timestamp conversion, not a conversion to the TIME type. The AT TIME ZONE form makes the conversion direction visible in the expression.
A fixed instant makes the difference between an instant and a UTC clock reading concrete. This Python illustration uses the standard library and prints a timestamp without its zone marker:
from datetime import datetime, timezone
instant = datetime(2026, 10, 23, 12, 0, tzinfo=timezone.utc)
utc_clock_reading = instant.astimezone(timezone.utc).replace(tzinfo=None)
print(utc_clock_reading.isoformat(sep=" "))
2026-10-23 12:00:00
This example illustrates the value shape produced by the SQL expression; the Python code does not execute SQL. Do not use now()::timestamp as a substitute for UTC conversion: casting a timestamp with time zone to timestamp without time zone uses the session time zone, so its clock fields depend on that setting. The interval form timezone(INTERVAL '+00:00', now()) also uses a zero offset and yields the UTC clock reading. A nonzero offset such as INTERVAL '-08:00' represents a different clock reading.
Use a SQL Function for a Reusable UTC Default
If several table definitions need the same expression, an optional SQL function can give it a reusable name. Define it to return timestamp without time zone: CREATE FUNCTION current_utc_timestamp() RETURNS timestamp without time zone LANGUAGE sql STABLE AS 'SELECT now() AT TIME ZONE ''UTC''';. Then use DEFAULT current_utc_timestamp() in a column definition.
The function packages the expression; it does not make the clock advance within a transaction or change the return type. As with the direct default, a column using this function receives its value when a row is inserted and only when the insert does not supply a value for that column. Keep the type aligned with the data’s meaning: use timestamp without time zone for a UTC clock reading whose UTC meaning is maintained by convention, and generally use timestamp with time zone when storing an instant.