postgresqldatetimetimestamptimestamp-with-timezone

For timestamp with timezone, the internally stored value is always in UTC


According to the documentation, "for timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system's TimeZone parameter, and is converted to UTC using the offset for the timezone zone.".

This explanation appears to conflict with the statement regarding the handling of timestamp with time zone. For instance, I set the system's TimeZone to US/Eastern and executed the command select '2025-02-12T6:30:04'::timestamptz. I anticipated the result to be 2025-02-12T11:30:04+00:00, as there is no time zone specified in the input string 2025-02-12T6:30:04. Therefore, it should default to the system's TimeZone parameter, which is US/Eastern, and subsequently convert to UTC using the offset between UTC and US/Eastern.

However, the actual return result was 2025-02-12T06:30:04-05:00, which represents a timestamp in US/Eastern rather than UTC.

Am I misunderstanding the documentation, or is there an error in the documentation itself?


Solution

  • Both results represent exactly the same timestamptz value, the same point in universal time (Einstein aside). Only the display differs. See what happens when I run this locally, with timezone = Europe/Vienna:

    test=> SELECT timestamptz '2025-02-12T11:30:04+00:00' AS t1
    test->      , timestamptz '2025-02-12T06:30:04-05:00' AS t2
    test->      , timestamptz '2025-02-12T06:30:04-05:00' = timestamptz '2025-02-12T11:30:04+00:00' AS the_same;
    
               t1           |           t2           | the_same 
    ------------------------+------------------------+----------
     2025-02-12 12:30:04+01 | 2025-02-12 12:30:04+01 | t
    

    I get a third, equivalent display for the same point in time. Postgres displays timestamptz values according to the timezone setting of the session. If you prefer timestamptz values to be displayed for the UTC timezone, you might tell Postgres that you currently operate in that time zone by setting your session variable: SET timezone = 'UTC';. Of course, Postgres will then assume UTC where no time zone is given explicitly.

    Also, time zone abbreviations like 'EST' are a crude tool that only encode a constant time offset. To be smart about daylight saving time (and other political changes across history), use a time zone name, like 'US/Eastern' - like Adrian already suggested in the comments.

    See the manual on time zones and:

    Don't fall for the idea that the data type timestamp with time zone would somehow carry a time zone. It does not. See: