PostgreSQL – Don't Do This
wiki.postgresql.org
wiki.postgresql.org
I literally DO NOT understand, how is this good advice.
My backend service exists in some abstraction of a Linux environment, with a fixed timezone, most commonly UTC. It maintains a pool of connections to Postgres, all sharing the same Postgres user, and the same timezone.
Why on earth would I prefer a timestampz to timestamp? Why would I even involve the server timezone into this equation?
I want to store timestamps in a uniform way, I store them in UTC as timestamps. If I stored them in a timestampz column, if the server timezone were to adjust, I'd get literally different values.
If I want to store timezone values per user (of my service), or per operation (that my users perform), then again, surely I have to handle that users move and change their timezones. Again, how does timestampz with its reliance on the connection timezone serve me?
The benefit to this vs a regular timestamp is that when you insert/update a timestamp value, Postgres can then convert that timestamp to UTC if necessary before storing it, and if you select a timestamp value Postgres can convert it from UTC to the timezone you want.
If your connection is set to use UTC, and you always handle UTC timestamps, there probably isn't much practical difference between `timestamp` and `timestamptz`, however.
server=# CREATE TABLE test1 (date TIMESTAMPTZ NOT NULL);
CREATE TABLE
server=# INSERT INTO test1 VALUES (NOW());
INSERT 0 1
server=# SELECT * FROM test1;
date
------------------------------2023-06-01 08:00:30.40968+02
(1 row)
server=# SET timezone = 'UTC';
server=# SELECT * FROM test1;
date
------------------------------2023-06-01 06:00:30.40968+00
(1 row)
Aren't timestamps always supposed to be utc?
I've seen both these things happen at companies. Often users don't care or notice for a long time, until suddenly they do and you're painted into a corner.
I dread timestamp issues. Hard to understand what happens and how to fix them.
You mention "if necessary". How does postgres knows if a conversion is necessary?
SELECT ('2023-03-12 03:00:00 America/New_York'::TIMESTAMP WITH TIME ZONE - '30m'::INTERVAL) AT TIME ZONE 'America/New_York'; -- Do some math over US DST switch
You need your initial datetime to have a time zone if you want to do math that's aware of time zones. And sadly if you don't store time zones (all times are "local"!) then you can't get that information back.
I think best practice is to have PostgreSQL run in UTC and always store a time zone, that way you're always aware of time zone info and aren't restricted in the future.
The problem here is actually knowing what time zone to use. You can get quagmired pretty quickly in like, do we surface this to users, do we use browser location, is there an address/location we can key off of, how do we update it as they move, blah blah. I understand the appeal of being time zone naive. But it's not cut and dry IME.
> I think best practice is to have PostgreSQL run in UTC and always store a time zone, that way you're always aware of time zone info and aren't restricted in the future.
- you're time zone aware but you have to deal with time zones
- you're time zone naive but you can't do anything you need time zones for, like converting between time zones or using time zones (and DST) in time zone math
I think the recommendation is "figure out how to get time zone info and store it, otherwise you foreclose time zone functionality and managing DST", but yeah up to you if you're willing to accept that risk.
- It doesn't know I was using EST, so it's off by 5 hours now.
- If I ever want to do math across the DST switch, I can't, because my original tzinfo was lost.
It's not wholly unreasonable to want to avoid time zones, but personally I think you should always be time zone aware and build it into your app in a reasonable way, though I recognize that's easier said than done. Mostly I guess my feeling is "get over it" though haha.
Then again, I think the most important thing overall is just that you should store your timestamps in UTC no matter how you do it. Worst is coming into databases and finding they are storing PST just because they happen to be there.
This seems counterintuitive, aren't timestamps essentially number of seconds passed since 1 jan 1970 00:00 utc?
For example, if a user can create an event scheduled in their timezone, you probably would want to use a `timestamp` and not `timestamptz`. This way, if the user schedules the event for e.g. 5:00pm, and then the time zone changes (think DST or similar), the event is still at 5:00pm (it won't get shifted like a `timestamptz` would).
Of course the default of the PostgreSQL driver for several ORMs of several languages is varchar(255).
Why ?
Because IF it's said not to do this, it should not be implemented in first place.
This is a trap.
For example, "Don't use table inheritance", you should always use this to reuse the table definition. If not, what's the alternative ?
Some of it exists for important reasons, that are documented on the page. For example, respecting the SQL standard, or maintaining compatibility with database from a time/system without the replacement feature, or for special circumstances that don't apply to you.