0

Does anyone know what this actually does?

There appears to be two different timezones, a Session timezone and a Database time zone. The former is clear, it causes timezones with timestamp to be converted from a text representation in psql to UTC.

But what does the Database time zone do?

It can be changed with ALTER DATABASE database_name SET TIMEZONE='zone';

Is Database Timezone just some sort of default for the Session Timezone? Or does it affect how timestamps are stored? My understanding is that the psql session timezone defaults to the client computer timezone.

There is also the question of the 99.9% of usages that do not use psql. Say JDBC. When and how are offsets added. But that is not this question.

Timezones are tricky, and never well documented.

Tuntable
  • 3,276
  • 1
  • 21
  • 26
  • 1
    Too many questions at once. Essentially, you are asking "tell me all about time zone management in PostgreSQL". The good message for you: if you use `timestamp without time zone`, the parameter `timezone` has no effect at all. – Laurenz Albe Oct 20 '22 at 10:50
  • 1
    1) Interestingly enough this is covered in the docs [Time zones](https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-TIMEZONES). 2) What are the ODBC bugs? – Adrian Klaver Oct 20 '22 at 15:52
  • @LaurenzAlbe there is one question, Database Timezone vs Sessioon timezone. I will make that clearer. – Tuntable Oct 22 '22 at 01:14
  • @LaurenzAlbe that page has no useful info on this. The nature of the ODBC bugs is irrelevant, just an explanation for why I do not do the obvious and use Timestamp with timezones. – Tuntable Oct 22 '22 at 01:15
  • 1
    "*How do you show the current Database Timezone?*" - see https://stackoverflow.com/q/53564718/1048572 or https://dba.stackexchange.com/q/220933/188406 – Bergi Nov 01 '22 at 03:43

3 Answers3

2

This is covered in the documentation. In particular:

For timestamp with time zone, the internally stored value is always in UTC […].

Admittedly mentioning UTC is a bit misleading, I'd prefer to say that a timestamptz represents an instant, an exact fixed point in time, without regard to calendar or location (timezone). It's just an offset since an epoch. Very much like a Date in Java or JavaScript, or better: like an Instant (Java, JavaScript).

[For literal timestamptz values, 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.

When a timestamp with time zone value is output, it is always converted from UTC to the current timezone zone, and displayed as local time in that zone.

The TimeZone configuration parameter can be set in the file postgresql.conf, or in any of the other standard ways described in Chapter 20.

TimeZone (string):
Sets the time zone for displaying and interpreting time stamps. The built-in default is GMT, but that is typically overridden in postgresql.conf; initdb will install a setting there corresponding to its system environment.

So the timezone setting affects conversions of timestamps from and to text, both via casting and the via to_char/to_timestamp function calls, in SQL execution.

It does not affect storage.

Looking at chapter 20, in particular Setting Parameters, shows that there are many more than just two places to set the timezone configuration variable.

The most fundamental way to set these parameters is to edit the file postgresql.conf. […]

Parameters set in this way provide default values for the cluster. The settings seen by active sessions will be these values unless they are overridden. The following sections describe ways in which the administrator or user can override these defaults.

[The file postgresql.auto.conf] is intended to be edited automatically, not manually. This file holds settings provided through the ALTER SYSTEM command. […] Settings in postgresql.auto.conf override those in postgresql.conf.

[T]here are two commands that allow setting of defaults on a per-database or per-role basis:

  • The ALTER DATABASE command allows global settings to be overridden on a per-database basis.
  • The ALTER ROLE command allows both global and per-database settings to be overridden with user-specific values.

Values set with ALTER DATABASE and ALTER ROLE are applied only when starting a fresh database session. They override values obtained from the configuration files or server command line, and constitute defaults for the rest of the session.

Once a client is connected to the database, PostgreSQL provides […] SQL commands […] to interact with session-local configuration settings:

  • The SET command allows modification of the current value of those parameters that can be set locally to a session; it has no effect on other sessions.

The documentation of the SET command details how this may be limited to the current session, the current transaction, or the currently executing function.

A client would have to explicitly set this to use the client computer's system timezone for the session. JDBC does this, for example.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thank you for taking the trouble to reply. However, you have not addressed the actual question. Timezone processing is complex, happens in multiple places, often wrong. I will improve the question. – Tuntable Nov 03 '22 at 05:42
  • "For timestamp with time zone, the internally stored value is always in UTC" is that actually true? Or is it stored internally in the Database Timezone, which defaults to UTC? How would you know? – Tuntable Nov 03 '22 at 05:48
  • Not sure which of your questions was the "actual" question, but I think I had covered them all. "*What does the Database time zone do?*" - it's a configuration setting that is applied when starting a fresh session (connection), overrides the server defaults, and constitutes the default for the rest of the session. "*Is Database Timezone just some sort of default for the Session Timezone?*" - yes. "*Or does it affect how timestamps are stored?*" - no. "*My understanding is that the psql session timezone defaults to the client computer timezone.*" - no: only when your client explicitly set it. – Bergi Nov 03 '22 at 08:53
  • "*"For timestamp with time zone, the internally stored value is always in UTC" is that actually true?*" - sure it is. `timestamp with timezone` represents an instant, a fixed point in time (called "exact time"), without regard to calendar or location (timezone). It's just an offset since an epoch. "*stored in UTC*" is actually misleading imo. – Bergi Nov 03 '22 at 08:58
  • your comments answer the actual question, but not your answer. Make it into a new answer and I would accept it. Plus what happens for JDBC, for cols timestamptz, values Date vs String. I would assume timezone settings have no effect on the former. Column timestamp no tz the opposite. – Tuntable Nov 05 '22 at 00:38
  • I've update my answer to include the info from my comments, I hope it is sufficient now. – Bergi Nov 05 '22 at 02:33
  • Re JDBC, I've not used it myself and don't know how it does conversion of raw serialisation to java objects. But I would presume that when you query `timestamptz` as a `Date`, `timezone` doesn't matter. When you query `timestamptz` as a `String`, the `timezone` would apply ("*When a `timestamp with time zone` value is output, it is always converted from UTC to the current `timezone` zone, and displayed as local time in that zone.*"). When you query `timestamp` as a `String`, it would not apply. And you shouldn't query a `timestamp` as a `Date` (JDBC might assume UTC? Postgres does not). – Bergi Nov 05 '22 at 02:38
  • thanks for your work, but the answer still does not reflect the comment. You could pretty much just cut paste the comment into the answer, and remove most of the rest of the answer. Also, there is timezone <-> timezonetz conversions. – Tuntable Nov 06 '22 at 09:27
  • What part of my comments is not reflected in the answer? I prefer elaborate answers with quotes from the documentation over yes/no statements. – Bergi Nov 06 '22 at 11:14
  • the comment and the answer are rather unrelated. I had read the manual. Maybe just replace the answer with the comment? – Tuntable Nov 08 '22 at 04:41
  • Fine, I've posted another answer with the gist of the comments. – Bergi Nov 08 '22 at 18:20
1

Manual ALTER DATABASE part.

The remaining forms change the session default for a run-time configuration variable for a PostgreSQL database. Whenever a new session is subsequently started in that database, the specified value becomes the session default value. The database-specific default overrides whatever setting is present in postgresql.conf or has been received from the postgres command line. Only the database owner or a superuser can change the session defaults for a database. Certain variables cannot be set this way, or can only be set by a superuser.

meaning if the new connection not explicitly override the value, then the new value will become session default.
Like ALTER DATABASE test15 SET TIMEZONE='Singapore'; if you are still in session, you will still have the previous timezone value, if you quit the session, reenter agagin, then the new TIMEZONE is Singapore.

    SELECT
    name,
    category,
    short_desc,
    extra_desc,
    context
FROM
    pg_settings
WHERE
    name = 'TimeZone' gx

return.

-[ RECORD 1 ]---------------------------------------------------------------
name       | TimeZone
category   | Client Connection Defaults / Locale and Formatting
short_desc | Sets the time zone for displaying and interpreting time stamps.
extra_desc |
context    | user

The context is user level, which means any connection can use set command change it.
So when query the interval value like timestamptz column > now(). the return values will become different for connections in differenent timezone.

psql session timezone defaults to the client computer timezone.

if you not explicitly set it, the default will be database level timezone parameter value.

There is also the question of the 99.9% of usages that do not use psql. Say JDBC. When and how are offsets added. But that is not this question.

psql is same as JDBC, both are client. they can change timezone use set command, if the connection is superuser or owner, then they can change database default, which means other connection will follow the new default. However each connection can still use set command to change the timezone paramter.

does it affect how timestamps are stored?

If your timestamp from string literal,then no. if your timezone from timestamptz then yes. First query result is the same, second is not.

begin;
set time zone 'Singapore';
select '2022-01-01 11:30'::timestamp;
reset time zone;
select '2022-01-01 11:30'::timestamp;
commit;

begin;
set time zone 'Singapore';
select now()::timestamp;
reset time zone; --default not 'Singapore'
select now()::timestamp;
commit;
jian
  • 4,119
  • 1
  • 17
  • 32
  • Thanks for this. But "timestamptz column > now(). the return values will become different for connections in differenent timezone." is not true, I just tested it. Now() is type timestamptz. – Tuntable Nov 05 '22 at 00:33
  • @Tuntable Yech I made a mistake. it should be `timestamptz column - now()` the return interval value will be differerent for different time zone. – jian Nov 05 '22 at 03:29
1

(another post answering exactly the questions from the OP, taken from the comments of my other answer)

What does the Database time zone do?

It's a configuration setting that is applied when starting a fresh session (connection), overrides the server defaults, and constitutes the default for the rest of the session.

Is Database Timezone just some sort of default for the Session Timezone?"

Yes.

Or does it affect how timestamps are stored?

No. timestamp with timezone represents an instant, a fixed point in time, without regard to calendar or location (timezone). It's just an offset since an epoch.

My understanding is that the psql session timezone defaults to the client computer timezone.

No: only when your client explicitly sets it - like JDBC does.

What happens for JDBC, for cols timestamptz, values Date vs String?

I've not used it myself and don't know how it does conversion of raw serialisation to java objects. But I would presume that when you query timestamptz as a Date, the timezone setting doesn't matter. When you query timestamptz as a String, the timezone would apply ("When a timestamp with time zone value is output, it is always converted from UTC to the current timezone zone, and displayed as local time in that zone.").
When you query timestamp as a String, it would not apply. And you shouldn't query a timestamp as a Date (JDBC might assume UTC? Postgres does not!)

How do you show the current Database Timezone?

See How do you view the configuration settings of a PostgreSQL database? or Query for all the Postgres configuration parameters‘ current values?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375