Thursday, May 31, 2018

timestamptz is easier to adjust than timestamp

create table z(id int primary key, _timestamp timestamp, _timestamptz timestamptz);
insert into z(id, _timestamp, _timestamptz) values (1, '2018-05-04T17:37:00Z', '2018-05-04T17:37:00Z');
set timezone to 'Asia/Manila';
select 
    _timestamp as "indeterminate timezone", -- timestamp is an indeterminate timezone. for the purpose of this demo, we are storing UTC-based data
    _timestamptz as "follows set timezone to XXX", 
    _timestamp at time zone 'UTC' at time zone 'Asia/Tokyo' as "local: Japan", 
    _timestamptz at time zone 'Asia/Tokyo' as "local: Japan",
    _timestamp at time zone 'UTC' at time zone 'Asia/Manila' as "local: Philippines", 
    _timestamptz at time zone 'Asia/Manila' as "local: Philippines"
from z;

-[ RECORD 1 ]---------------+-----------------------
indeterminate timezone      | 2018-05-04 17:37:00
follows set timezone to XXX | 2018-05-05 01:37:00+08
local: Japan                | 2018-05-05 02:37:00
local: Japan                | 2018-05-05 02:37:00
local: Philippines          | 2018-05-05 01:37:00
local: Philippines          | 2018-05-05 01:37:00

set timezone to 'Asia/Tokyo';
select 
    _timestamp as "indeterminate timezone", -- timestamp is an indeterminate timezone. for the purpose of this demo, we are storing UTC-based data
    _timestamptz as "follows set timezone to XXX", 
    _timestamp at time zone 'UTC' at time zone 'Asia/Tokyo' as "local: Japan", 
    _timestamptz at time zone 'Asia/Tokyo' as "local: Japan",
    _timestamp at time zone 'UTC' at time zone 'Asia/Manila' as "local: Philippines", 
    _timestamptz at time zone 'Asia/Manila' as "local: Philippines"
from z;

-[ RECORD 1 ]---------------+-----------------------
indeterminate timezone      | 2018-05-04 17:37:00
follows set timezone to XXX | 2018-05-05 02:37:00+09
local: Japan                | 2018-05-05 02:37:00
local: Japan                | 2018-05-05 02:37:00
local: Philippines          | 2018-05-05 01:37:00
local: Philippines          | 2018-05-05 01:37:00


If we use timestamp field type instead of timestamptz, everytime we need to see the local time in another time zone, we have to convert it to UTC first before we can convert it to a local timezone, e.g.,

_timestamp at time zone 'UTC' at time zone 'Asia/Tokyo' as "local: Japan", 
_timestamp at time zone 'UTC' at time zone 'Asia/Manila' as "local: Philippines", 

Whereas if we use timestamptz upfront, we don't need to convert the data to UTC first before we can adjust it to local, we can just adjust it straight to local, e.g.,
_timestamptz at time zone 'Asia/Tokyo' as "local: Japan",
_timestamptz at time zone 'Asia/Manila' as "local: Philippines"

Another benefit of using timestamptz field type and saving UTC-based data to it, is we can set a local timezone per database session, and Postgres will present the UTC data in local timezone, e.g.,
set timezone to 'Asia/Manila';

select 
    _timestamptz as "follows set timezone to XXX"
from z;

-[ RECORD 1 ]---------------+-----------------------
follows set timezone to XXX | 2018-05-05 01:37:00+08

select 
    _timestamptz + interval '1 day' as "follows set timezone to XXX"
from z;

-[ RECORD 1 ]---------------+-----------------------
follows set timezone to XXX | 2018-05-06 01:37:00+08



set timezone to 'Asia/Tokyo';

select 
    _timestamptz as "follows set timezone to XXX"
from z;

-[ RECORD 1 ]---------------+-----------------------
follows set timezone to XXX | 2018-05-05 02:37:00+09

select 
    _timestamptz + interval '1 day' as "follows set timezone to XXX"
from z;

-[ RECORD 1 ]---------------+-----------------------
follows set timezone to XXX | 2018-05-06 02:37:00+09



set timezone to 'UTC';

select 
    _timestamptz as "follows set timezone to XXX"
from z;

-[ RECORD 1 ]---------------+-----------------------
follows set timezone to XXX | 2018-05-04 17:37:00+00

select 
    _timestamptz + interval '1 day' as "follows set timezone to XXX"
from z;

-[ RECORD 1 ]---------------+-----------------------
follows set timezone to XXX | 2018-05-05 17:37:00+00

Whereas if we used timestamp field type instead of timestamptz, Postgres won't apply set timezone to XXX to the timestamp field type, timestamp is always presented as-is. And usage of timestamp field type should be documented, since timestamp is an indeterminate timezone, no one knows whether the developer designed it to be stored of local timezone, or was it designed to be stored of UTC data. Whereas with timestamptz, it is implied that we should only store UTC-based data to it, doing otherwise is a fool's errand.

No comments:

Post a Comment