PG SQL 10 set default time zone to UTC - postgresql

I need to change the database config to use UTC as the default for a PostgreSQL10 instance hosted on AWS RDS. I want it permanently changed at the database level and to never revert back to any other timezone no matter what.
I've tried running this, but it shows 0 updated rows:
ALTER DATABASE <my-db> SET timezone='UTC';
I've tried attaching a custom param group to the DB in RDS and modifying the entries like so (also rebooted after):
No matter what I do, when I run select * from pg_settings where name = 'TimeZone'; or SHOW timezone it shows 'America/Chicago'.
It seems like this should be easy to do, but it is proving to be a challenge.

If you want to store your timestamps in UTC and always want the database to send the data to the client in UTC as well, you should use the data type timestamp without time zone, which will not perform any time zone handling for you. That would be the simplest solution.
To convert the data, you could proceed like this:
SET timezone = 'UTC';
ALTER TABLE mytable ALTER timestampcol TYPE timestamp without time zone;

Based on this dba.stackexchange.com question. Apparently PG stores the timestamp in UTC time but then converts it to the session time zone. From what I've gathered, since my timestamps don't include time zone information, I need to tell PG that the timezone being stored is UTC, and then convert that to whatever local time is needed, so something like this:
SELECT my_timestamp_in_utc AT TIME ZONE 'UTC' AT TIME ZONE 'America/Denver' as my_local_time
FROM my_table;
This is a little verbose, but I'll go with it for now.

Related

Vertx Oracle Datetime in LocalTime

Version
Vertx 4.3.4, JDBCClient
Questions
Our Oracle-database is setup in the local-timezone "Europe/Vienna" and returns the local-time over JDBC. But within the convertion of the VertX-JDBC the time markt in any case to UTC.
If you do a
pool.preparedQuery("select SESSIONTIMEZONE as sessionTimeZone, sysdate as dateValue, to_char(sysdate,'yyyy-dd-mm hh24:mi:ss') localTime from dual")
The output will be:
"sessionTimeZone":"Europe/Vienna",
"dateValue":"2022-10-17T10:06:45Z",
"localTime":"2022-17-10 10:06:45"
I assume it is related to this code-part (JDBCDecoderImpl.java, Line 188), where the returned timestamp is set hard-coded to UTC:
if (descriptor.jdbcType() == JDBCType.TIMESTAMP || descriptor.jdbcType() == JDBCType.TIMESTAMP_WITH_TIMEZONE) {
return LocalDateTime.parse(value.toString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME).atOffset(ZoneOffset.UTC);
}
The oracle-jdbc-driver always return the timestamp in the timezone the database is setup. There is no possibility as it is at MySQL, where the timezone could be defined.
Is there a way to workaround this conversion?
This is a known issue from JDBC with Oracle Databases. In order to correctly set the timezone (without requiring any code changes) you can issue the following statement at start of each connection:
ALTER SESSION SET TIME_ZONE = 'UTC'
This will allow you to set the timezone for the session which should match the application. In this case, UTC.
There are other options too. For example if you can modify the database you can set the database timezone at creation time:
CREATE DATABASE myDB
...
SET TIME_ZONE='UTC';
Or modify it after creation:
ALTER DATABASE myExistingDB
...
SET TIME_ZONE='UTC';
If you don't want/can alter the database and want to keep using the vert.x client without managing the connection yourself, in other words, keep using 1 shot queries, you can specify at the query level the timezone too:
SELECT
FROM_TZ(TIMESTAMP '2030-01-01 12:30:35', '-04:00')
AT TIME ZONE '+12:00'
FROM DUAL;

LAMBDA current_timestamp towards Postgres

Question is very simple:
We are executing select current_timestamp from lambda to PostgreSQL aurora (which is set to america/New_york timezone).
Scenario:
When we execute select Current_timestamp directly in PostgreSQL Server, it is giving the time in EST.
But when we execute the same form Lambda, it is giving UTC time zone.
I know that Lambda timezone is UTC.
But I am confused here, because am picking up this piece of code "select Current_timestamp" from dynamoDB and passing it as a string through lambda towards PostgreSQL. And I can see this statement is exciting in PostgreSQL too. It should pick up the timezone of PostgreSQL. Not sure why it is picking Lambda.
Need to fix this and I need to execute this statement from Lambda and get the Current_timestamp of PostgreSQL(Not LAMBDA)
current_timestamp returns the timestamp formatted for the current session, which may be in UTC. You have a few options:
SELECT current_timestamp at time zone 'America/New_York'; This is the most explicit.
Start each session with SET TIME ZONE 'America/New_York';
ALTER USER youruser SET TIME ZONE 'America/New_York'; This will default the user to this time zone, but the client can still override this.

Is there any equivallent function in postgres like systimestamp() of oracle

I'm working on a oracle to postgresql database migration project. I need to read operating system date and time from postgres. In oracle sysdate() returns system date time in date type data and systimestamp() returns timestamp type data whatever the time_zone variable set. But in postgres current_date() and current_timestamp() always give the result relative to the timezone variable set for that database.
Synchronizing the timezone variable (i.e. set timezone='utc') is one way, but I don't want my timezone variable to be changed.
All I want to get is the current date and time of my system (time zone may include or not) like in oracle. Any pl/pgsql would be helpful. Thanks
The data type TIMESTAMP WITH TIME ZONE is different in Oracle and PostgreSQL.
While Oracle stores the timestamp information along with the timestamp, PostgreSQL stores the timestamp in UTC and displays it in the currently set time zone (available with the SQL statement SHOW TimeZone).
So the functions return the same time in PostgreSQL and Oracle, but it is displayed in a different fashion. That should normally be no problem.
If you really need to store time zone information along with a timestamp, you'll have to use a separate field to store the time zone information. You can then use AT TIME ZONE to convert the timestamp to that time zone for display.

Why would select localtimestamp return different timezones on 2 different machines with Postgres

If I execute on Postgres 9.2
show timezone
on my machine, it returns the local time zone
America/Denver
when I run the same postgres command on the guy beside me, it returns
US/Eastern
Anyone know why the Postgres Server would use two different timezones for 2 different people?
The statement show time zone shows the time zone of the current client's session. That might or might not be the time zone of the PostgreSQL server.
To see how this works, open two terminal sessions on the same computer, and connect each of them to your database with psql. (I'm connecting to a database named "sandbox". My PostgreSQL server is set to local time. That is, postgresql.conf has the line timezone = 'localtime'.)
In the first session, set the time zone to Berkeley, Calif.
sandbox=# set time zone 'PST8PDT';
(The default scope for set is session. This statement is equivalent to set session time zone 'PST8PDT';.)
In the second session, set the time zone to UTC.
sandbox=# set time zone 'UTC';
Neither of these are my local time zone.
Now run show time zone in each session. The first one will return 'PST8PDT'; the second will return 'UTC'. The server's time zone is still local time.
If I drop one of the connections, and I connect again, I go back to local time.
sandbox=# show time zone;
TimeZone
-----------
localtime

Changing time zone value of data

I have to import data without time zone information in it (however, I know the specific time zone of the data I want to import), but I need the timestamp with time zone format in the database. Once I import it and set the timestamp data type to timestamp with time zone, Postgres will automatically assume that the data in the table is from my time zone and assign my time zone to it. Unfortunately the data I want to import is not from my time frame, so this does not work.
The database also contains data with different time zones. However, the time zone within one table is always the same.
Now, I could set the time zone of the database to the time zone of the data I want to import before importing the data (using SET time zone command) and change it back to my time zone once the import is done, and I am pretty sure already stored data will not be affected by the time zone change of the database. But this seems to be a pretty dirty approach and may cause problems later on.
I wonder if there is a more elegant way to specify the time zone for the import without having the time zone data in the data itself?
Also, I have not found a way to edit time zone information after import. Is there a way not to convert, but simply to edit the time zone for a whole table, assuming that the whole table has the same time zone offset (i.e. if a wrong one has been assigned upon data entry/import)?
Edit:
I managed to specify a time zone upon import, the whole command being:
set session time zone 'UTC';
COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV;
set session time zone 'CET';
The data then gets imported using the session time zone. I assume this has no effect on any other queries on the database at the same time from other connections?
Edit 2:
I found out how to change the time zone of a table afterwards:
PostgreSQL update time zone offset
I suppose it is more elegant to change the time zone of the table after import then to use session to change the local time zone temporary. Assuming the whole table has the same time zone of course.
So the code would be now something along the line of:
COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV;
UPDATE tbl SET <tstz_field> = <tstz_field> AT TIME ZONE '<correct_time_zone>';
It is a lot more efficient to set the time zone for your import session than to update the values later.
I get the impression that you think of the time zone like a setting that applies to otherwise unchanged values in the tables. But it's not like that at all. Think of it as an input / output modifier. Actual timestamp values (with or without time zone) are always stored as UTC timestamps internally (number of seconds since '2000-01-01 00:00'). A lot more details:
Ignoring time zones altogether in Rails and PostgreSQL
The UPDATE in your second example doubles the size of the table, as every single row is invalidated and a new version added (that's how UPDATE works with MVCC in Postgres). In addition to the expensive operation, VACUUM will have to do more work later to clean up the table bloat. Very inefficient.
It is perfectly safe to SET the local time zone for the session. This doesn't affect concurrent operations in any way. BTW, SET SESSION is the same as plain SET because SESSION is the default anyway.
If you want to be absolutely sure, you can limit the setting to the current transaction with SET LOCAL. I quote the manual here
The effects of SET LOCAL last only till the end of the current
transaction, whether committed or not. A special case is SET followed
by SET LOCAL within a single transaction: the SET LOCAL value will be
seen until the end of the transaction, but afterwards (if the
transaction is committed) the SET value will take effect.
Put together:
BEGIN;
SET LOCAL timezone = 'UTC';
COPY tabledata FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV;
COMMIT;
Check:
SHOW timezone;