I setup a postgres db that was installed on a server in the Central Time Zone so all the timestamp columns are in Central Time Zone.
Is there a way in postgres to change all the timezone columns in a database from CST to GMT? Is it a best practice to configure databases to use GMT?
Well, best practice is to avoid using TIMESTAMP type which does not know anything about timezones and to always use TIMESTAMPTZ (short for TIMESTAMP WITH TIME ZONE) type to store your timestamps.
TIMESTAMPTZ stores both timestamp in UTC and timezone in which timestamp was originally written to (like CST, PST or GMT+6). This allows you to always manipulate and display these columns correctly, no matter what current server or client timezone setting is.
You should be able to convert your existing TIMESTAMP columns into TIMESTAMPTZ using something like:
ALTER TABLE mytable ALTER COLUMN old_tstamp TYPE TIMESTAMPTZ
Before doing this, you should experiment on small dataset or maybe small test table on how conversion from TIMESTAMP to TIMESTAMPTZ is really working for you such that time zone information is preserved on your data.
If conversion does not work correctly, you can temporarily set timezone for current session (you need it only for conversion purposes) using statement like (use it before ALTER TABLE ... COLUMN ... TYPE):
SET timezone TO 'CST6CDT';
or
SET timezone TO 'UTC+6';
This will affect subsequent operations and conversions from TIMESTAMP to TIMESTAMPTZ - just make sure to get it right.
After you have converted all timestamps to TIMESTAMPTZ, server or client timezone setting (which defaults to current operating system timezone setting) is only useful for display purposes, as data manipulation will be always correct.
Related
I have a table that contains a timestamp column. whenever I try to access the endpoint it returns timestamp data as UTC timestamp. I want the timestamp data without UTC conversion.
I have a column text_ts which is a text field that always holds data representing a timestamptz, just as a text field. I need to create an index on it such as:
CREATE INDEX IF NOT EXISTS text_ts_timestamp_idx ON my_schema.my_table ((text_ts::timestamptz AT TIME ZONE 'UTC'));
However I get the error:
functions in index expression must be marked IMMUTABLE
I have found this: https://dba.stackexchange.com/questions/250627/why-isnt-it-possible-to-cast-to-a-timestamp-in-an-index-in-postgresql which seems to have a recommended way to handle timestamp, but I can't seem to get it to work for timestamptz AT TIME ZONE 'UTC'.
Anyone have any ideas?
I am replicating tables in Postgres to Snowflake and run into these types of tstzrange and tsrange in Postgres which I am not sure whether Snowflake supports.
I see something like TIMESTAMP_LTZ, TIMESTAMP_NTZ and TIMESTAMP_TZ in Snowflake documentation (https://docs.snowflake.net/manuals/sql-reference/data-types-datetime.html#timestamp-ltz-timestamp-ntz-timestamp-tz). But these are not range types.
What would be the best way to support these range timestamp types from Postgres in Snowflake?
In Postgres
tsrange contains timestamp without time zone
tstzrange contains timestamp with time zone
The Snowflake alias for timestamp_ntz and timestamp_tz matches exactly to the Postgres type.
Now the Postgres ranges actually contain 3 items: lower range, upper range, and boundary inclusion/exclusion. It's the boundary that may cause issues - you may have to manually alter queries to accommodate them. Also watch out for Infinity (+-) in the ranges. (See sections 8.17.3 and 8.17.4 in above referenced documentation.)
I have a table in Oracle with timestamp data in "JAN-16-15 05.10.14.034000000 PM".
When I created the table in postgresql with "col_name timestamp" it is showing data as "2015-01-16 17:10:14.034".
Any suggestions on how can set the column to get the data format as in postgre same to what I have in Oracle?
Timestamps (or dates or numbers) do not have any "format2. Neither in Postgres nor in Oracle or in any other relational database).
Any "format" you see, is applied by your SQL client displaying those values.
You need to configure your SQL client to use a different format for timestamp, or use the to_char() function to format the value as you want.
In particular, to get the format you desire, use
SELECT to_char(current_timestamp, 'MON-MM-YY HH.MI.SS.US000 AM');
The output format can be changed in psql by changing the DateStyle parameter, but I would strongly recommend to not change it away from the default ISO format as that also affects the input that is parsed.
I am working wih a PostgreSQL DB that stores time-series data.
The data is stored using "timestamp with time zone" type and the output is ISO format (postgresql default). The data source is a closed-source software that creates tables with "timestamp with time zone" data type.
The precision of the timestamp is till 6 digits (microseconds) according to Postgres documentation. So, my time-series are recorded every second and I see milliseconds in the output.
e.g. 2012-06-25 15:46:23.001
The software that plots the time-series data goes crazy with the milliseconds but I can't modify the data source software to use timestamp(0) when it creates the tables.
A colleague of mine programmed a function that queries the whole database to alter the timestamp data type to "timestamp(0) with time zone" in every table. It works well but it's a manual action that has to be done after every new table is created. We would like to avoid the use of the function.
Is it possible to tell to postgresql to create timestamp(0) timestamp data types instead of the default timestamp(6) by editing postgresql.conf?
This handling is very deeply hardcoded and cannot easily be changed by a user. (See AdjustTimestampForTypmod() in the source code, if you are curious.)
You could create a view over the table that casts the timestamp column to timestamp(0) or formats it perhaps using to_char, and point your rendering software at that view.
The trick (do not perform it on the production DB!):
postgres=# alter type timestamptz rename to timestamptz6;
ALTER TYPE
postgres=# create domain pg_catalog.timestamptz as timestamptz6(0);
CREATE DOMAIN
postgres=# create table t (tz1 timestamp with time zone, tz2 timestamptz);
CREATE TABLE
postgres=# insert into t values(now(), now());
INSERT 0 1
postgres=# select * from t;
╔════════════════════════╤════════════════════════╗
║ tz1 │ tz2 ║
╠════════════════════════╪════════════════════════╣
║ 2016-08-11 21:06:17+03 │ 2016-08-11 21:06:17+03 ║
╚════════════════════════╧════════════════════════╝
(1 row)
Voila! Thats it.
Now lets restore everything as it was before:
postgres=# drop table t;
DROP TABLE
postgres=# drop domain pg_catalog.timestamptz;
DROP DOMAIN
postgres=# alter type timestamptz6 rename to timestamptz;
ALTER TYPE
Use it at your own risk. And good luck.