As you already found out, the time zone is not saved at all with Postgres date / time types, even with timestamptz . Its role is only an input modifier or output decoder, respectively. Only the value (point in time) is saved. Enough details in this answer:
Therefore, if you want to save this part of the input string, you need to extract it from the string and save it yourself. I would use a table like:
CREATE TABLE tstz ... , ts timestamp
tz , being text , may contain a numerical offset , as well as a time zone abbreviation or time zone name .
The difficulty is to extract a part of the time zone in accordance with all the various rules that the parser follows, and in such a way that it will not break easily. Instead of preparing your own procedure, make the parser do the work . Consider this demo:
WITH ts_literals (tstz) AS ( VALUES ('2013-11-28 23:09:11.761166+03'::text) ,('2013-11-28 23:09:11.761166 CET') ,('2013-11-28 23:09:11.761166 America/New_York') ) SELECT tstz ,tstz::timestamp AS ts ,right(tstz, -1 * length(tstz::timestamp::text)) AS tz FROM ts_literals;
SQL Fiddle
Works with or without T between date and time. The key logic here is:
right(tstz, -1 * length(tstz::timestamp::text)) AS tz
Take what remains of the timestamp string after trimming the length of what the parser defines as a date / time component. It depends on the input, as you stated:
ISO8601 verified strings