Comment obtenir lhorodatage UNIX actuel de PostgreSQL?

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| */ 

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

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.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *