Fiquei surpreso select date_trunc('day','2021-02-16 20:00+04'::timestamptz);
ao retornar 2021-02-17 00:00:00+08
no postgres.
É como se tivéssemos avançado no tempo do dia 16 para o dia 17.
Quero verificar meu entendimento e encontrar fontes que expliquem isso (de preferência oficiais).
A sessão temset timezone = 'Asia/Singapore'; --utc+8
Meu entendimento
Há duas transformações acontecendo antes do truncamento:
- 20:00+04 se transforma em 16:00+00 armazenado como um inteiro de 8 bits (tempo de época em microssegundos) que o postgres usa para representar instantes no tempo físico (em oposição ao tempo civil mencionado em https://errorprone.info/docs/time )
- Quando
date_trunc
executado, 16:00+00 se torna no dia seguinte 00:00+08 porquedate_trunc
interpreta no horário local (fuso horário da sessão)
Testei a hipótese alterando a entrada para 2021-02-16 20:00+05
, que gera 2021-02-16 00:00:00+08
. (sem incremento de dia).
Acho que isso ocorre porque a 1ª transformação retrocedeu mais 1 hora, para 15:00+00, então a 2ª transformação só chegou às 23:00 do dia 16, em vez de meia-noite do dia 17?
Não consegui encontrar nenhum documento mencionando esse comportamento de dupla interpretação. O mais próximo está abaixo:
Quando o valor de entrada é do tipo timestamp com fuso horário, o truncamento é executado com relação a um fuso horário específico; por exemplo, o truncamento para day produz um valor que é meia-noite naquele fuso horário. Por padrão, o truncamento é feito com relação à configuração TimeZone atual, mas o argumento opcional time_zone pode ser fornecido para especificar um fuso horário diferente.
https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC