Skip to content
EL
Contents

SQL types and the type system

Dates, times and time zones

ConceptFoundation3 min read10 min hands-on#fundamentals#sql#data-modeling

The idea in 30 seconds

timestamptz stores one exact instant and shows it in whatever time zone your session uses. timestamp without time zone stores only the clock reading and throws away any offset you give it. For anything that happened at a moment in time (orders, payments, logins), use timestamptz.

Helps to know first: SQL data modification

On this page

Two kinds of timestamp

PostgreSQL has two timestamp types, and the names are misleading:

TypeWhat it storesOn output
timestamptz (timestamp with time zone)One exact instant, kept internally in UTCConverted to the session’s time zone
timestamp (without time zone)A date and a clock reading, nothing moreExactly as stored

Despite its name, timestamptz does not remember the time zone you gave it. It uses the zone to work out the exact instant, stores that instant, and forgets the zone.

See the difference

Store the moment Asha placed her first order, 10:15 in Pune, in both types:

CREATE TEMP TABLE events (label text, with_tz timestamptz, without_tz timestamp);
INSERT INTO events VALUES
  ('order placed in Pune', '2025-03-02 10:15+05:30', '2025-03-02 10:15+05:30');

Now read it back from sessions in three different time zones:

Session time zonewith_tzwithout_tz
UTC2025-03-02 04:45:00+002025-03-02 10:15:00
Asia/Kolkata2025-03-02 10:15:00+05:302025-03-02 10:15:00
America/New_York2025-03-01 23:45:00-052025-03-02 10:15:00

with_tz is the same instant every time, shown on three different clocks: in New York it was still the evening before. without_tz says “10:15” everywhere, and nothing in it tells you where those 10:15 were. The +05:30 in the input was silently thrown away.

PredictComparing two orders

A customer in New York and a customer in Pune each place an order at “10:15 on 2 March” on their own clocks. The times are stored in a timestamp (without time zone) column. Which order came first?

Showing local time

To display an instant as a particular place’s local time, use AT TIME ZONE:

SELECT ordered_at, ordered_at AT TIME ZONE 'Asia/Kolkata' AS pune_local_time
FROM orders WHERE id = 101;
       ordered_at       |   pune_local_time
------------------------+---------------------
 2025-03-02 04:45:00+00 | 2025-03-02 10:15:00

The result is a plain clock reading for display, not an instant to store.

When plain timestamp and date are right

  • date for things that are a whole day wherever you are: a birthday, a joining date, an invoice date. customers.joined_on is a date.
  • timestamp without time zone for a wall-clock time that should not move with the viewer: “the shop opens at 09:00”, in whichever city the shop is.

Everything that happened at a moment, use timestamptz.

Check yourself

  1. What does timestamptz actually store?

    Show answer

    One exact instant, held internally as UTC. The time zone given on input is used to compute that instant and is then discarded; output is converted to the session’s time zone.

  2. You insert '2025-03-02 10:15+05:30' into a timestamp column. What is stored?

    Show answer

    2025-03-02 10:15:00. For timestamp without time zone, PostgreSQL silently ignores the offset, so the information about which 10:15 is lost.

  3. Which type for an order’s placed-at time, a user’s birthday, and a store’s daily opening time?

    Show answer

    timestamptz for the order (a moment), date for the birthday (a whole day), and time or timestamp without time zone for the opening time (a wall-clock reading).

Finished reading?

Saved in this browser only.

Sources

Where each claim on this page comes from.

  1. 1.
    PostgreSQL documentation: 8.5 Date/Time Types
    Primary· §8.5.1.3 Time Stamps

    For timestamp with time zone, input is converted to UTC and stored as UTC, the original zone is not kept, and output is converted to the session's TimeZone; for timestamp without time zone, any zone in the input is silently ignored.

  2. 2.
    PostgreSQL documentation: 9.9 Date/Time Functions and Operators
    Primary· §9.9.4 AT TIME ZONE and AT LOCAL

    AT TIME ZONE converts a timestamp with time zone to the local time in a given zone, as a timestamp without time zone.

Go further

What to read next, and why it is worth the time.

  1. 1.
    PostgreSQL documentation: 8.5 Date/Time Types
    Primary· §8.5.1.3 Time Stamps, §8.5.3 Time Zones

    The precise rules for both timestamp types and how PostgreSQL names time zones.

Applies to PostgreSQL 18. Draft: not yet fact-checked end to end.