web-dev-qa-db-fra.com

Transformez la représentation de date postgres en chaîne ISO 8601

J'essaie de formater une représentation de date Postgres en une chaîne ISO 8601. Je suppose qu'il existe une fonction Postgres qui peut le faire, mais j'ai trouvé la documentation courte sur des exemples.

Ma requête est

SELECT
  now()::timestamp

qui revient

[{{2016, 8, 9}, {3, 56, 55, 754181}}]

J'essaie de mettre la date dans un format qui ressemble plus à 2016-8-9T03:56:55+00:00.

Quels changements dois-je apporter à ma requête pour que cela se produise? Merci de votre aide.

25
CallMeNorm

Je pense avoir trouvé un moyen de faire le formatage, mais ce n'est pas idéal car j'écris le formatage moi-même.

Voici une solution potentielle:

SELECT to_char (now()::timestamp at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')
24
CallMeNorm

Peut-être que pour quelqu'un, il serait utile de savoir que depuis Postgres 9.4 to_json fonction (ainsi que row_to_json) convertit également l'horodatage au format ISO 8601 approprié, mais en plus, il encapsule une valeur entre guillemets qui pourrait ne pas être souhaitable:

SELECT now();
  2017-05-10 15:57:23.736054+03

SELECT to_json(now());
  "2017-05-10T15:57:23.769561+03:00"

-- in case you want to trim the quotes
SELECT trim(both '"' from to_json(now())::text);
  2017-05-10T15:57:23.806563+03:00
19
Dattaya

C'est une manière laconique de "transformer une représentation de date PostgreSQL en une chaîne ISO 8601":

SELECT to_json(now())#>>'{}'

Il utilise l'opérateur #>> En combinaison avec la fonction to_json(), qui se trouvent toutes les deux sur cette page: https://www.postgresql.org/docs/current/ functions-json.html

L'opérateur "Get [s] JSON object at specified path as text". Cependant, lorsque vous spécifiez un littéral de tableau vide '{}' Comme chemin, il spécifie l'objet racine.

Comparez cette méthode à des méthodes similaires:

SELECT
to_json(now())::text AS has_unwanted_quotes,
trim(both '"' from to_json(now())::text) AS a_bit_lengthy,
to_json(now())#>>'{}' AS just_right

Il est plus court mais produit les mêmes résultats.

5
adjenks

Définissez la variable de session timezone sur le fuseau horaire dans lequel vous souhaitez que la sortie soit, puis utilisez to_char(now(), 'YYYY-MM-DD"T"HH24:MI:SSOF')

Si tu utilises at time zone '...' sachez que cela supprimera toutes les informations de fuseau horaire et supposera que l'utilisateur connaît déjà le fuseau horaire.

Si tu utilises at time zone 'UTC' alors la sortie doit toujours être l'heure UTC, avec des informations de fuseau horaire correctes (pas de décalage).

set timezone='UTC';


select to_char(now(), 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T02:02:26+00  /* UTC time */


select to_char(now() at time zone 'Australia/Sydney', 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T13:02:26+00  /* Local Sydney time, but note timezone is incorrect. */


set timezone='Australia/Sydney';


select to_char(now(), 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T13:02:26+11  /* Local Sydney time with correct time zone! */


select to_char(now() at time zone 'Australia/Sydney', 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T13:02:26+00  /* Still local Sydney time, but time zone info has been removed. */


select to_char(now() at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SSOF');

2017-11-17T02:02:26+00  /* Correct UTC time with correct offset. */

Ce billet de blog donne une explication assez détaillée.

4
Hugh

Seule la fonction a fonctionné pour moi car vous devez définir le fuseau horaire.

Pour avoir un fuseau horaire avec une zone par défaut:

create table somedata (
  release_date timestamptz DEFAULT NOW()
)

Créer fonction :

CREATE OR REPLACE FUNCTION date_display_tz(param_dt timestamp with time zone)
 RETURNS text AS
$$
DECLARE var_result varchar;
BEGIN
PERFORM set_config('timezone', 'UTC', true);
var_result := to_char(param_dt , 'YYYY-MM-DD"T"HH24:MI:SS:MS"Z"');
RETURN var_result;
END;
$$ language plpgsql VOLATILE;

Et sortie:

# SELECT
#   localtimestamp, current_timestamp,
#   to_char(localtimestamp, 'YYYY-MM-DD"T"HH24:MI:SS:MS"Z"'),
#   to_char(current_timestamp, 'YYYY-MM-DD"T"HH24:MI:SS:MS"Z"'),
#   date_display_tz(localtimestamp), date_display_tz(current_timestamp);
         timestamp          |              now              |         to_char          |         to_char          |     date_display_tz      |     date_display_tz
----------------------------+-------------------------------+--------------------------+--------------------------+--------------------------+--------------------------
 2017-04-27 23:48:03.802764 | 2017-04-27 21:48:03.802764+00 | 2017-04-27T23:48:03:802Z | 2017-04-27T23:48:03:802Z | 2017-04-27T21:48:03:802Z | 2017-04-27T21:48:03:802Z
(1 row)

Regardez this aussi:

Si vous souhaitez que le serveur renvoie des informations de fuseau horaire respectives d'un autre fuseau horaire, je pense que vous devrez utiliser SET TIME ZONE. Sinon, le serveur automatiquement (convertit l'horodatage) et renvoie le fuseau horaire du serveur.

test=# select (current_timestamp at time zone 'UTC') at time zone 'UTC';
            timezone
-------------------------------
  2005-04-22 16:26:57.209082+09
(1 row)

test=# set time zone 'UTC';
SET
test=# select (current_timestamp at time zone 'UTC') at time zone 'UTC';
            timezone
-------------------------------
  2005-04-22 07:27:55.841596+00
(1 row)

test=# select (current_timestamp at time zone 'UTC');
           timezone
----------------------------
  2005-04-22 07:28:48.888154
(1 row)

test=# select (current_timestamp at time zone 'UTC')::timestamptz;
            timezone
-------------------------------
  2005-04-22 07:38:19.979511+00
(1 row)
3
rofrol