Again, that depends on how you look at it. In fact in both cases you can corner yourself into difficult to debug bugs.
Here’s the thing, if you use timestamp without time zone type, when you select * from something
you will always get the value you inserted before. So, no matter what client’s time zone was when inserting 10:00 00:00:00
, it will always return you 10:00 00:00:00
. However, the NOW()
will return different value depending on your client’s locale.
So, if you have a query like SELECT * FROM foo where CREATED_AT < NOW()
this will lead to a bug if your connecting client’s time zone is not what you expect it to be.
On the other hand, if you use timestamp with time zone you will not have this bug, because NOW()
, and the CREATED_AT
field will be shifted to the same local time zone client uses. But you are then prone to errors if your client inserts values using SQL client, as you need to make sure these are now in local time as well - and not UTC. If your client is then set to “Europe/Warsaw”, the values you insert need to be local for timestamp with time zone.
Luckily, whatever you do, while you are using only Ecto/Postgrex to access your database, it will always treat the dates as UTC, because the binary protocol only uses UTC. So whichever type you use, as long as you convert the zones in your app, you are safe.
It can bite you in the behind when you either import data, or run reports using external scripts, however. Either way, it’s good idea to treat dates in import as UTC, and shift client zone to UTC in your reporting and importing scripts with SET TIME ZONE UTC
, or avoid doing that sort of things completely.