Dans postgres, timestamp with time zonepeut être abrégé en timestamptz, et timestamp without time zoneen timestamp. Je vais utiliser les noms de types les plus courts pour plus de simplicité.
Obtenir le timestamp Unix depuis un postgres timestamptzlike now()est simple, comme vous dites, simplement:
select extract(epoch from now());
C'est tout ce que vous devez savoir pour obtenir l'heure absolue de tout type timestamptz, y compris now().
Les choses ne se compliquent que lorsque vous avez un timestampchamp.
Lorsque vous placez des timestamptzdonnées comme now()dans ce champ, elles sont d'abord converties dans un fuseau horaire particulier (explicitement avec at time zoneou en convertissant dans le fuseau horaire de la session) et les informations relatives au fuseau horaire sont supprimées . Il ne fait plus référence à un temps absolu. C’est la raison pour laquelle vous ne souhaitez généralement pas stocker les horodatages de la manière timestamphabituelle timestamptz. Un film est peut-être diffusé à 18 heures à une date donnée, dans chaque fuseau horaire , c’est le genre de cas d’utilisation.
Si vous ne travaillez que dans un seul fuseau horaire, vous pouvez vous en tirer (mal) timestamp. La conversion vers timestamptzest suffisamment intelligente pour prendre en charge l'heure d'été, et les horodatages sont supposés, pour les besoins de la conversion, se trouver dans le fuseau horaire actuel. Voici un exemple pour GMT / BST:
select '2011-03-27 00:59:00.0+00'::timestamptz::timestamp::timestamptz
, '2011-03-27 01:00:00.0+00'::timestamptz::timestamp::timestamptz;
/*
|timestamptz |timestamptz |
|:---------------------|:---------------------|
|2011-03-27 00:59:00+00|2011-03-27 02:00:00+01|
*/
DBFiddle
Mais notez le comportement déroutant suivant:
set timezone to 0;
values(1, '1970-01-01 00:00:00+00'::timestamp::timestamptz)
, (2, '1970-01-01 00:00:00+02'::timestamp::timestamptz);
/*
|column1|column2 |
|------:|:---------------------|
| 1|1970-01-01 00:00:00+00|
| 2|1970-01-01 00:00:00+00|
*/
DBFiddle
C'est parce que :
PostgreSQL ™ n'examine jamais le contenu d'une chaîne littérale avant de déterminer son type, et traitera donc les deux […] comme des horodatages sans fuseau horaire. Pour vous assurer qu'un littéral est traité comme un horodatage avec fuseau horaire, donnez-lui le type explicite correct… Dans un littéral déterminé comme étant un horodatage sans fuseau horaire, PostgreSQL ™ ignorera en silence toute indication de fuseau horaire.