PostgreSQL GETDATE() Equivalent: now() and SYSDATE
TL;DR: PostgreSQL has no GETDATE() or SYSDATE. Use now() (or the SQL-standard CURRENT_TIMESTAMP) for the current date and time, CURRENT_DATE for today's date, and clock_timestamp() when you need the real wall-clock time that keeps moving inside a transaction.
The PostgreSQL equivalent of SQL Server's GETDATE() and Oracle's SYSDATE is now(). It returns a timestamp with time zone (timestamptz) with microsecond precision, for example 2019-12-23 14:39:53.662522-05 in the official docs. Calling GETDATE() in PostgreSQL fails with ERROR: function getdate() does not exist, and a bare SYSDATE fails with column "sysdate" does not exist. The one behavior that surprises people moving from SQL Server: now() is frozen at the start of the current transaction, so it returns the same value for every row and every statement inside one transaction.
What is the PostgreSQL equivalent of GETDATE() and SYSDATE?
PostgreSQL replaces the vendor functions with a small family of current-time functions, documented in section 9.9.5 of the PostgreSQL manual. This is the mapping:
You used | Engine | PostgreSQL equivalent | Returns
GETDATE() | SQL Server | LOCALTIMESTAMP or now()::timestamp | timestamp (no time zone)
SYSDATETIMEOFFSET() | SQL Server | now() / CURRENT_TIMESTAMP | timestamptz
GETUTCDATE() / SYSUTCDATETIME() | SQL Server | now() AT TIME ZONE 'UTC' | timestamp in UTC
CAST(GETDATE() AS date) | SQL Server | CURRENT_DATE | date
SYSDATE | Oracle | LOCALTIMESTAMP(0) or now() | timestamp
SYSTIMESTAMP | Oracle | now() | timestamptz
NOW() / SYSDATE() | MySQL | now() / clock_timestamp() | timestamptz
Microsoft's GETDATE reference says GETDATE() returns a datetime "without the database time zone offset", taken from the operating system clock of the SQL Server host. Oracle's SYSDATE likewise returns the database server operating system's date and time as a DATE, formatted by NLS_DATE_FORMAT. PostgreSQL's closest literal match for both is LOCALTIMESTAMP, but in practice most teams use now() and store timestamptz, because an offset-free timestamp is ambiguous the moment a second server or time zone appears.
SELECT now(); , 2026-10-13 09:41:07.218334+05:30
SELECT CURRENT_TIMESTAMP; , same value as now()
SELECT CURRENT_DATE; , 2026-10-13
SELECT LOCALTIMESTAMP; , 2026-10-13 09:41:07.218334 (no offset)
SELECT now()::date; , 2026-10-13What is the difference between now(), CURRENT_TIMESTAMP and clock_timestamp()?
They differ in when the time is captured. The PostgreSQL docs define five non-standard time functions plus the SQL-standard keywords:
Function | Captured at | Changes within a statement? | Type
now() | start of current transaction | No | timestamptz
CURRENT_TIMESTAMP / transaction_timestamp() | start of current transaction | No | timestamptz
statement_timestamp() | receipt of the latest command from the client | No | timestamptz
clock_timestamp() | the instant the function is called | Yes | timestamptz
timeofday() | the instant called (historical) | Yes | text
CURRENT_DATE | start of current transaction | No | date
LOCALTIMESTAMP | start of current transaction | No | timestamp
The docs call the frozen transaction time "a feature": every row written in one transaction gets the same timestamp, so an order and its line items share an exact created_at. statement_timestamp() and now() are equal for the first statement of a transaction and can differ for later ones.
BEGIN;
SELECT now(), statement_timestamp(), clock_timestamp();
SELECT pg_sleep(2);
SELECT now(), statement_timestamp(), clock_timestamp();
now() is unchanged; the other two moved forward by about 2 seconds
COMMIT;Use clock_timestamp() to time steps inside a long function or to log progress in a batch job. Use now() for everything else.
How do you get only the current date or time?
CURRENT_DATE returns today's date as a date with no time part; it is the replacement for SQL Server's CAST(GETDATE() AS date) and Oracle's TRUNC(SYSDATE).
SELECT CURRENT_DATE; , 2026-10-13
SELECT CURRENT_TIME; , 09:41:07.218334+05:30 (timetz)
SELECT LOCALTIME; , 09:41:07.218334 (time)
SELECT date_trunc('day', now()); , 2026-10-13 00:00:00+05:30 (timestamptz)
SELECT CURRENT_TIMESTAMP(0); , rounded to whole secondsCURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME and LOCALTIMESTAMP accept an optional precision argument that rounds the fractional seconds; CURRENT_TIMESTAMP(2) returns two decimal places. Note: "today" is computed in the session's TimeZone setting, so a server running in UTC and a session set to Asia/Kolkata can disagree about the date for 5 hours and 30 minutes each day.
How do time zones affect now() in PostgreSQL?
now() returns an absolute instant; PostgreSQL stores timestamptz internally in UTC and displays it in the session's TimeZone. Changing the time zone changes the display, not the moment.
SHOW TimeZone; , e.g. UTC
SET TIME ZONE 'America/New_York';
SELECT now(); , shown with -04 or -05 offset
SELECT now() AT TIME ZONE 'UTC'; , timestamp (no tz) in UTC, like GETUTCDATE()
SELECT now() AT TIME ZONE 'Asia/Kolkata'; , local wall-clock time in IndiaAT TIME ZONE applied to a timestamptz returns a timestamp without time zone, which is exactly the shape of SQL Server's GETUTCDATE(). Managed services such as Amazon RDS, Supabase and Neon default the server TimeZone to UTC, so dashboards that look "a day off" usually need AT TIME ZONE before date_trunc. Our PostgreSQL CAST guide covers converting between timestamp, timestamptz and date safely.
How do you use now() as a column default?
Use the function call now() (or CURRENT_TIMESTAMP) in the DEFAULT clause, never the string literal 'now'.
CREATE TABLE events (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);The PostgreSQL docs warn that DEFAULT TIMESTAMP 'now' is converted to a constant when the table is created, so every row would get the table's creation time. Function calls are evaluated on each insert. For an updated_at column, PostgreSQL has no ON UPDATE CURRENT_TIMESTAMP like MySQL; use a BEFORE UPDATE trigger that sets NEW.updated_at = now().
Can you use now() in an index or generated column?
No. now() and CURRENT_TIMESTAMP are marked STABLE, not IMMUTABLE, because their result changes between transactions. PostgreSQL only allows immutable functions in index expressions, partial-index WHERE clauses and GENERATED ALWAYS AS (...) STORED columns, so CREATE INDEX ... WHERE created_at > now() - interval '30 days' fails with functions in index predicate must be marked IMMUTABLE.
What does work: a plain B-tree index on created_at, used by queries such as WHERE created_at >= now() - interval '30 days'. Because now() is stable, the planner evaluates it once per query and can use the index for the range scan. If you need a "recent rows" index, put a fixed cut-off date in the partial-index predicate and rebuild it periodically.
How do you filter rows relative to the current date?
Combine now() or CURRENT_DATE with an interval. This replaces SQL Server patterns like WHERE created_at >= DATEADD(day, -7, GETDATE()).
Last 7 days, rolling (keeps the time of day)
SELECT * FROM orders WHERE created_at >= now() - interval '7 days';
Since midnight 7 days ago
SELECT * FROM orders WHERE created_at >= CURRENT_DATE - 7;
This calendar month so far
SELECT * FROM orders WHERE created_at >= date_trunc('month', now());
Age of each open ticket in hours
SELECT id, EXTRACT(EPOCH FROM now() - opened_at) / 3600 AS hours_open
FROM tickets WHERE status = 'open';Keep the column bare on the left (created_at >= ...) so an index on created_at can be used; wrapping the column, as in created_at::date = CURRENT_DATE, can prevent index use. For the full date-arithmetic toolkit see DATEADD in PostgreSQL and DATEDIFF in PostgreSQL.
How do you convert common GETDATE() queries to PostgreSQL?
Converting T-SQL date code is mostly mechanical once you know the replacements. These are the idioms that show up most in SQL Server reports and stored procedures:
SQL Server | PostgreSQL
SELECT GETDATE() | SELECT now()
CONVERT(date, GETDATE()) | CURRENT_DATE
DATEADD(day, -30, GETDATE()) | now() - interval '30 days'
DATEADD(month, 1, GETDATE()) | now() + interval '1 month'
DATEDIFF(day, created_at, GETDATE()) | CURRENT_DATE - created_at::date
YEAR(GETDATE()) | EXTRACT(YEAR FROM now())
DATEPART(weekday, GETDATE()) | EXTRACT(DOW FROM now()) (0 = Sunday)
EOMONTH(GETDATE()) | (date_trunc('month', now()) + interval '1 month - 1 day')::date
DATEFROMPARTS(2026, 1, 1) | make_date(2026, 1, 1)
FORMAT(GETDATE(), 'yyyy-MM') | to_char(now(), 'YYYY-MM')
Two traps when porting. First, SQL Server's DATEPART(weekday, ...) depends on the SET DATEFIRST setting (default 7, Sunday = 1), while PostgreSQL's EXTRACT(DOW ...) is fixed at Sunday = 0 and EXTRACT(ISODOW ...) at Monday = 1. Second, GETDATE() is evaluated per statement in SQL Server, whereas now() is per transaction, so a stored procedure that relied on timestamps advancing between statements needs clock_timestamp() or statement_timestamp() instead.
How do you format the current date in PostgreSQL?
to_char() formats a timestamp as text, replacing SQL Server's CONVERT(varchar, GETDATE(), 23) and FORMAT(GETDATE(), 'yyyy-MM-dd').
SELECT to_char(now(), 'YYYY-MM-DD'); , 2026-10-13
SELECT to_char(now(), 'YYYY-MM-DD HH24:MI:SS'); , 2026-10-13 09:41:07
SELECT to_char(now(), 'Dy, DD Mon YYYY'); , Tue, 13 Oct 2026
SELECT EXTRACT(YEAR FROM now()), EXTRACT(MONTH FROM now());Format only for display. Comparing or sorting formatted strings breaks as soon as the pattern changes; compare the timestamps themselves.
If you query dates like this every week for reports, AI for Database lets you ask "orders in the last 7 days by day" in plain English against PostgreSQL, MySQL or SQL Server and writes the engine-correct date SQL, so the GETDATE() vs now() translation is handled for you.
FAQ
Does PostgreSQL have GETDATE()?
No. GETDATE() is SQL Server syntax and raises function getdate() does not exist in PostgreSQL. Use now(), CURRENT_TIMESTAMP, or LOCALTIMESTAMP for a value without time zone.
What is SYSDATE in PostgreSQL?
PostgreSQL has no SYSDATE. Oracle's SYSDATE maps to LOCALTIMESTAMP(0) for date and time to the second, or CURRENT_DATE for date only. Oracle migration tools such as Orafce provide a sysdate() function, but plain PostgreSQL does not.
Is now() the same as CURRENT_TIMESTAMP?
Yes. Both return the start time of the current transaction as timestamptz. now() is the traditional PostgreSQL name; CURRENT_TIMESTAMP is the SQL-standard keyword and is written without parentheses.
Why does now() return the same time in my loop?
Because now() is fixed at transaction start. Inside a function, DO block or long transaction, use clock_timestamp() to get the time that advances on every call.
Does now() return UTC?
It returns an absolute moment displayed in the session TimeZone. If the server or session is set to UTC you see UTC; otherwise use now() AT TIME ZONE 'UTC'.
What is the PostgreSQL equivalent of NOW() in MySQL?
now(), with one difference: MySQL's NOW() returns the statement start time, while PostgreSQL's now() returns the transaction start time. MySQL's SYSDATE() behaves like PostgreSQL's clock_timestamp().