Horodatage Unix est le nombre de secondes depuis le 1er janvier 1970 à minuit UTC.
Comment obtenir le bon horodatage Unix de PostgreSQL?
En comparant avec currenttimestamp.com et timestamp.1e5b.de Je nobtiens pas lheure attendue de PostgreSQL:
Ceci renvoie lhorodatage correct:
SELECT extract(epoch from now());
Bien que cela ne « t:
SELECT extract(epoch from now() at time zone "utc");
Je vis dans le fuseau horaire UTC +02. Quelle est la bonne façon dobtenir lhorodatage Unix actuel de PostgreSQL?
Ceci renvoie lheure et le fuseau horaire corrects:
SELECT now(); now ------------------------------- 2011-05-18 10:34:10.820464+02
Autre comparaison:
select now(), extract(epoch from now()), extract(epoch from now() at time zone "utc"); now | date_part | date_part -------------------------------+------------------+------------------ 2011-05-18 10:38:16.439332+02 | 1305707896.43933 | 1305700696.43933 (1 row) Unix timestamp from the web sites: 1305707967
Réponse
Dans postgres, timestamp with time zone
peut être abrégé en timestamptz
et timestamp without time zone
en timestamp
. Jutiliserai les noms de type plus courts pour plus de simplicité.
Obtenir lhorodatage Unix à partir dun postgres timestamptz
comme now()
est simple, comme vous le dites, juste:
select extract(epoch from now());
Cest vraiment tout ce que vous devez savoir pour obtenir lheure absolue à partir de tout type de timestamptz
, y compris now()
.
Les choses ne se compliquent que lorsque vous avez un champ timestamp
.
Lorsque vous insérez des données timestamptz
telles que now()
dans ce champ, elles seront dabord converties dans un fuseau horaire particulier (soit explicitement avec at time zone
soit en effectuant une conversion vers le fuseau horaire de la session) et les informations de fuseau horaire sont supprimées . Elles ne font plus référence à une heure absolue. Cest pourquoi vous ne voulez généralement pas stocker les horodatages sous la forme timestamp
et utilisez normalement timestamptz
– peut-être quun film sortira à 18 heures sur un date dans chaque fuseau horaire , cest le genre de cas dutilisation.
Si vous ne travaillez que dans un seul fuseau horaire, vous pourriez vous en tirer (mis) en utilisant timestamp
. La reconversion en timestamptz
est suffisamment intelligente pour gérer lheure dété, et les horodatages sont supposés, à des fins de conversion, être 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| */
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| */
Ce est parce que :
PostgreSQL nexamine jamais le contenu dune chaîne littérale avant de déterminer son type et traitera donc les deux […] comme un horodatage sans fuseau horaire. assurez-vous quun littéral est traité comme horodatage avec fuseau horaire, donnez-lui le type explicite correct… Dans un littéral qui a été déterminé comme horodatage sans fuseau horaire, PostgreSQL ignorera silencieusement toute indication de fuseau horaire
Commentaires
- Toute idée de la façon de convertir le décimal résultant en un entier sans point décimal (je veux dire fusionner le nombre et le décimal comme un grand entier). Merci.
- Comme ceci mais je ' je suis sûr que vous navez ' pas vraiment envie de faire cela. Peut-être voulez-vous multiplier par une puissance de dix et supprimer les décimales restantes?
- @ W.M. Peut-être comme ça?
SELECT FLOOR(EXTRACT(epoch FROM NOW())*1000);
Réponse
SELECT extract(epoch from now() at time zone "utc");
ne renvoie pas lhorodatage correct car la conversion du fuseau horaire postgres supprime les informations de fuseau horaire du résultat:
9.9.3. AU FUSEAU HORAIRE
Syntaxe: horodatage sans fuseau horaire AT TIME ZONE zone
Renvoie: horodatage avec fuseau horaire
Traite lhorodatage donné sans fuseau horaire comme situé dans le fuseau horaire spécifiéSyntaxe: horodatage avec fuseau horaire AU fuseau horaire
Renvoie: horodatage sans fuseau horaire
Convertit lhorodatage donné avec fuseau horaire dans le nouveau fuseau horaire, sans désignation de fuseau horaire
ensuite, extraire regarde lhorodatage sans fuseau horaire et considère quil sagit dune heure locale (bien quelle soit déjà utc en fait).
La bonne façon serait:
select now(), extract(epoch from now()), -- correct extract(epoch from now() at time zone "utc"), -- incorrect extract(epoch from now() at time zone "utc" at time zone "utc"); -- correct now | date_part | date_part | date_part -------------------------------+------------------+------------------+------------------ 2014-10-14 10:19:23.726908+02 | 1413274763.72691 | 1413267563.72691 | 1413274763.72691 (1 row)
Dans la dernière ligne, le premier at time zone
effectue la conversion, le seco Un autre attribue un nouveau fuseau horaire au résultat.