Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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>';
like image 461
harbun Avatar asked Oct 01 '12 14:10

harbun


People also ask

How do I change the time zone on my database?

Use the ALTER DATABASE SET TIME_ZONE command to change the time zone of a database. This command takes either a named region such as America/Los_Angeles or an absolute offset from UTC. This example sets the time zone to UTC: ALTER DATABASE SET TIME_ZONE = '+00:00';

How do I change the time zone in SQL?

Changing the database timezone SQL Server users typically fetch the local timezone by using the GETDATE() function with insert/update statements or as a default constraint for a datetime column in a select statement.

How do I change timezone in autonomous database?

You can use the "alter database set time_zone" command and restart the database to change the timezone. Note that if you are using sysdate and systimestamp, those will still return in UTC. You can use the sysdate_at_dbtimezone parameter to make them return in the database timezone you set.

What is time zone values?

In ISO 8601, the particular zone offset can be indicated in a date or time value. The zone offset can be Z for UTC or it can be a value "+" or "-" from UTC. For example, the value 08:00-08:00 represents 8:00 AM in a time zone 8 hours behind UTC, which is the equivalent of 16:00Z (8:00 plus eight hours).


1 Answers

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;
like image 77
Erwin Brandstetter Avatar answered Sep 21 '22 08:09

Erwin Brandstetter