Yes, PostgreSQL stores all timestamps as UTC internally. For timestamp with time zone offset is used only to set the time to UTC, but is not saved explicitly.
I would not save a time zone line or even less time zone abbreviations (they are inaccurate). Subsequently, this may require expensive calculations, because you need to consider daylight saving time and other oddities of the international time regime.
You can either save the time zone offset as an interval (takes 12 bytes ) or a number of seconds (takes 4 bytes as an integer), as I demonstrate in this related answer .
Or, as you suggested: keep a local timestamp in addition to the UTC timestamp (accepts 8 bytes ). This will simplify your tasks. Consider the following demo:
-- DROP TABLE tbl; CREATE TEMP TABLE tbl (id int, ts_tz timestamp with time zone, ts timestamp); INSERT INTO tbl VALUES (1,'2012-1-1 00:00+01','2012-1-1 00:00+01') ,(2,'2012-1-1 00:00+02','2012-1-1 00:00+02') ,(3,'2012-1-1 00:01+03','2012-1-1 00:01+03') ,(4,'2012-1-1 00:02+04','2012-1-1 00:02+04');
Request for question 1:
SELECT * FROM tbl WHERE ts = '2012-1-1 00:00'::timestamp; id | ts_tz | ts
Request for question 2:
SELECT * FROM tbl ORDER BY ts_tz; id | ts_tz | ts
the tricky part with this solution may be to enter a local timestamp. This is easy if all data is entered locally. But it needs to be considered if you enter data, for example, in New York in Los Angeles. Use AT TIME ZONE construct for this:
SELECT ('2012-1-1 00:00+00' AT TIME ZONE 'America/New_York')::timestamp , ('2012-1-1 00:00+00' AT TIME ZONE 'America/Los_Angeles')::timestamp timezone | timezone
Notice how I use a timestamp with a timezone as input. AT TIME ZONE gives different results for timestamps with or without a time zone.