oky_sabeni
oky_sabeni

Reputation: 7822

How do I prevent Redshift INSERT datetime from dropping the timezone?

I have a String in this format: 2018-11-01T00:00:00-07:00 and I would like to convert it to a TIMESTAMP and insert it into a TIMESTAMP column. However, when I insert it, it drops the -07:00 without first converting it to -00:00. How do I ensure that it is converted and stored in Redshift properly?

Here is an example: select ORIGINAL_DATE, TO_TIMESTAMP(ORIGINAL_DATE,'YYYY-MM-DD HH24:MI:SS') FROM CDW_LANDING.X where id = XXXXXX;

=> 2018-11-01T00:00:00-07:00 2018-10-31 17:00:00

The TO_TIMESTAMP converts it to 2018-10-31 17:00:00 which is what I want. However, when I insert it, it becomes 2018-11-01 00:00:00 and simply drops the -07:00.

Here is the example:

insert into cdw_stage.X (ORIG_DT) 
select TO_TIMESTAMP(ORIGINAL_DATE,'YYYY-MM-DD HH24:MI:SS') 
from CDW_LANDING.INVOICE where id = XXXXXX;

But when I query it with select ORIG_DT from cdw_landing.X;, it displays 2018-11-01 00:00:00. What I would like to see is 2018-10-31 17:00:00 which is what the TO_TIMESTAMP function should do.

The ORIG_DT in Redshift is in TIMESTAMP format. The input date is in VARCHAR.

How do I get Redshift to save this correctly? I also added postgres tag because Redshift is based off of postgres. Thank you so much!!!

Upvotes: 1

Views: 7660

Answers (1)

Erwin Brandstetter
Erwin Brandstetter

Reputation: 656804

2018-11-01T00:00:00-07:00 is not a timestamp (timestamp without time zone) literal, strictly speaking. It is a timestamptz (timestamp with time zone) literal. This is the root of all pain in your question. The wrong cast to timestamp ignores the offset. The Postgres manual:

In a literal that has been determined to be timestamp without time zone, PostgreSQL will silently ignore any time zone indication. That is, the resulting value is derived from the date/time fields in the input value, and is not adjusted for time zone.

Bold emphasis mine.

The use of TO_TIMESTAMP() can't save you. The Redshift manual:

Formats that include a time zone (TZ, tz, or OF) are not supported as input.

(The same is true in Postgres.)

Solution

Cast to timestamptz (or use a column of that type to begin with), the rest should fall in place:

SELECT cast('2018-11-01T00:00:00-07:00' AS timestamptz);

Or:

SELECT '2018-11-01T00:00:00-07:00'::timestamptz;

The manual about casting in Redshift.

When an actual timestamptz is assigned to a timestamp column it is converted according to the current timezone setting of the session automatically. If you want a different target timezone, use the AT TIME ZONE construct. Details:

The related answer is for Postgres, but timestamp handling in Redshift (while differing in many other aspects!) is the same. The Redshift manual:

When converting DATE or TIMESTAMP to TIMESTAMPTZ, DATE or TIMESTAMP are assumed to use the current session time zone. The session time zone is UTC by default. For more information about setting the session time zone, see timezone.

Upvotes: 6

Related Questions