I’m having an issue selecting dates properly from Postgres – they are being stored in UTC, but
not converting with the Date() function properly.
Converting the timestamp to a date gives me the wrong date if it’s past 4pm PST.
2012-06-21 should be 2012-06-20 in this case.
The starts_at column datatype is timestamp without time zone. Here are my queries:
Without converting to PST timezone:
Select starts_at from schedules where id = 40;
starts_at
---------------------
2012-06-21 01:00:00
Converting gives this:
Select (starts_at at time zone 'pst') from schedules where id = 40;
timezone
------------------------
2012-06-21 02:00:00-07
But neither convert to the correct date in the timezone.
I don’t see the exact type of
starts_atin your question. You really should include this information, it is the key to the solution. I’ll have to guess.PostgreSQL always stores UTC time for the type
timestamp with time zoneinternally. Input and output (display) are adjusted to the currenttimezonesetting or to the given time zone. The effect ofAT TIME ZONEalso changes with the underlying data type. See:If you extract a
datefrom typetimestamp [without time zone], you get the date for the current time zone. The day in the output will be the same as in the display of thetimestampvalue.If you extract a
datefrom typetimestamp with time zone(timestamptzfor short), the time zone offset is "applied" first. You still get the date for the current time zone, which agrees with the display of the timestamp. The same point in time translates to the next day in parts of Europe, when it is past 4 p.m. in California for instance. To get the date for a certain time zone, applyAT TIME ZONEfirst.Therefore, what you describe at the top of the question contradicts your example.
Given that
starts_atis atimestamp [without time zone]and the time on your server is set to the local time. Test with:Does it display the same time as a clock on your wall? If yes (and the db server is running with correct time), the
timezonesetting of your current session agrees with your local time zone. If no, you may want to visit the setting oftimezonein yourpostgresql.confor your client for the session. Details in the manual.Be aware that the
timezoneoffset used the opposite sign of what’s displayed in timestamp literals. See:To get your local date from
starts_atjustTantamount to:
BTW, your local time is at UTC-7 right now, not UTC-8, because daylight savings time is in effect (not among the brighter ideas of the human race).
Pacific Standard TIME (PST) is normally 8 hours "earlier" (bigger
timestampvalue) than UTC (Universal Time Zone), but during daylight saving periods (like now) it can be 7 hours. That’s whytimestamptzis displayed as2012-06-21 02:00:00-07in your example. The constructAT TIME ZONE 'PST'takes daylight saving time into account. These two expressions yield different results (one in winter, one in summer) and may result in different dates when cast: