PostgreSQLLa base de données la plus sophistiquée au monde.

Version anglaise

8.5. Types date/heure

PostgreSQL™ supporte l'ensemble des types date et heure du SQL. Ces types sont présentés dans le Tableau 8.9, « Types date et heure ». Les opérations disponibles sur ces types de données sont décrites dans la Section 9.9, « Fonctions et opérateurs sur date/heure ». Les dates sont comptées suivant le calendrier grégorien, même dans le cas des dates antérieures à l'introduction du calendrier (voir) Section B.6, « Histoire des unités » pour plus d'informations).

Tableau 8.9. Types date et heure

Nom Taille de stockage Description Valeur minimale Valeur maximale Résolution
timestamp [ (p) ] [ without time zone ] 8 octets date et heure (sans fuseau horaire) 4713 avant JC 294276 après JC 1 microseconde / 14 chiffres
timestamp [ (p) ] with time zone 8 octets date et heure, avec fuseau horaire 4713 avant JC 294276 après JC 1 microseconde / 14 chiffres
date 4 octets date seule (pas d'heure) 4713 avant JC 5874897 après JC 1 jour
time [ (p) ] [ without time zone ] 8 octets heure seule (pas de date) 00:00:00.00 24:00:00 1 microseconde / 14 chiffres
time [ (p) ] with time zone 12 octets heure seule, avec fuseau horaire 00:00:00+1559 24:00:00-1559 1 microseconde / 14 chiffres
interval [ champs ] [ (p) ] 16 octets intervalles de temps -178000000 années 178000000 années 1 microseconde / 14 chiffres

[Note]

Note

Le standard SQL impose que timestamp soit un équivalent de timestamp without time zone. timestamptz est accepté comme abréviation pour timestamp with time zone ; c'est une extension PostgreSQL™.

time, timestamp, et interval acceptent une précision optionnelle p, qui indique le nombre de décimales pour les secondes. Il n'y a pas, par défaut, de limite explicite à cette précision. Les valeurs acceptées pour p s'étendent de 0 à 6 pour les types timestamp et interval.

[Note]

Note

Quand des valeurs de type timestamp sont stockées sur des entiers de 8 octets (ce qui est la valeur par défaut actuelle), la précision à la microseconde près est disponible sur tout le spectre des valeurs. Quand les timestamp sont stockés en nombres à virgule flottante double précision à la place (une option de compilation obsolète), la limite effective de précision peut être inférieure à 6. Les valeurs de type timestamp sont stockées en secondes avant ou après le 01/01/2000 à minuit. Quand les valeurs timestamp sont implémentées avec des nombres à virgule flottante, la précision à la microseconde n'est obtenue que sur les quelques années autour du 01/01/2000, et décroît pour les dates plus éloignées. Notez qu'utiliser des types date à virgule flottante permet d'avoir une plus grande étendue de timestamp : de 4713 av. J.-C. à 5874897 ap. J.-C., à la différence de ce qui est écrit plus haut.

La même option de compilation détermine aussi si les valeurs de type time et interval sont stockées en tant que nombres à virgule flottante ou entiers de 8 octets. Dans le cas de la virgule flottante, la précision des valeurs de type interval se dégradent avec leur accroissement.

Pour les types time, l'intervalle accepté pour p s'étend de 0 à 6 pour les entiers sur 8 octets et de 0 à 10 pour les nombres à virgule flottante.

Le type interval a une option supplémentaire, qui permet de restreindre le jeu de champs stockés en écrivant une de ces expressions :

    YEAR
    MONTH
    DAY
    HOUR
    MINUTE
    SECOND
    YEAR TO MONTH
    DAY TO HOUR
    DAY TO MINUTE
    DAY TO SECOND
    HOUR TO MINUTE
    HOUR TO SECOND
    MINUTE TO SECOND
   

Notez que si champs et p sont tous les deux indiqués, champs doit inclure SECOND, puisque la précision s'applique uniquement aux secondes.

Le type time with time zone est défini dans le standard SQL, mais sa définition lui prête des propriétés qui font douter de son utilité. Dans la plupart des cas, une combinaison de date, time, timestamp without time zone et timestamp with time zone devrait permettre de résoudre toutes les fonctionnalités de date et heure nécessaires à une application.

Les types abstime et reltime sont des types de précision moindre, utilisés en interne. Il n'est pas recommandé de les utiliser dans de nouvelles applications, car ils pourraient disparaître dans une prochaine version.

8.5.1. Saisie des dates et heures

La saisie de dates et heures peut se faire dans la plupart des formats raisonnables, dont ISO8601, tout format compatible avec SQL, le format POSTGRES™ traditionnel ou autres. Pour certains formats, l'ordre des jours, mois et années en entrée est ambigu. Il est alors possible de préciser l'ordre attendu pour ces champs. Le paramètre datestyle peut être positionné à MDY pour choisir une interprétation mois-jour-année, à DMY pour jour-mois-année ou à YMD pour année-mois-jour.

PostgreSQL™ est plus flexible que la norme SQL ne l'exige pour la manipulation des dates et des heures. Voir l'Annexe B, Support de date/heure pour connaître les règles exactes de reconnaissance des dates et heures et les formats reconnus pour les champs texte comme les mois, les jours de la semaine et les fuseaux horaires.

Tout libellé de date ou heure saisi doit être placé entre apostrophes, comme les chaînes de caractères. La Section 4.1.2.7, « Constantes d'autres types » peut être consultée pour plus d'information. SQL requiert la syntaxe suivante :

type [ (p) ] 'valeur'

p, précision optionnelle, est un entier correspondant au nombre de décimales du champ secondes. La précision peut être précisée pour les types time, timestamp, et interval. Les valeurs admissibles sont mentionnées plus haut. Si aucune précision n'est indiquée dans une déclaration de constante, celle de la valeur littérale est utilisée.

8.5.1.1. Dates

Le Tableau 8.10, « Saisie de date » regroupe les formats de date possibles pour la saisie de valeurs de type date.

Tableau 8.10. Saisie de date

Exemple Description
1999-01-08 ISO-8601 ; 8 janvier, quel que soit le mode (format recommandé)
January 8, 1999 sans ambiguïté quel que soit le style de date (datestyle)
1/8/1999 8 janvier en mode MDY ; 1er août en mode DMY
1/18/1999 18 janvier en mode MDY ; rejeté dans les autres modes
01/02/03 2 janvier 2003 en mode MDY ; 1er février 2003 en mode DMY ; 3 février 2001 en mode YMD
1999-Jan-08 8 janvier dans tous les modes
Jan-08-1999 8 janvier dans tous les modes
08-Jan-1999 8 janvier dans tous les modes
99-Jan-08 8 janvier en mode YMD, erreur sinon
08-Jan-99 8 janvier, sauf en mode YMD : erreur
Jan-08-99 8 janvier, sauf en mode YMD : erreur
19990108 ISO-8601 ; 8 janvier 1999 dans tous les modes
990108 ISO-8601 ; 8 janvier 1999 dans tous les modes
1999.008 Année et jour de l'année
J2451187 Date du calendrier Julien
January 8, 99 BC Année 99 avant Jésus Christ

8.5.1.2. Heures

Les types « heure du jour » sont time [ (p) ] without time zone et time [ (p) ] with time zone. time est équivalent à time without time zone.

Les saisies valides pour ces types sont constituées d'une heure suivie éventuellement d'un fuseau horaire (voir le Tableau 8.11, « Saisie d'heure » et le Tableau 8.12, « Saisie des fuseaux horaires »). Si un fuseau est précisé pour le type time without time zone, il est ignoré sans message d'erreur. Si une date est indiquée, elle est ignorée, sauf si un fuseau horaire impliquant une règle de changement d'heure (heure d'été/heure d'hiver) est précisé, America/New_York par exemple. Dans ce cas, la date est nécessaire pour pouvoir déterminer la règle de calcul de l'heure qui s'applique. Le décalage approprié du fuseau horaire est enregistré dans la valeur de time with time zone.

Tableau 8.11. Saisie d'heure

Exemple Description
04:05:06.789 ISO 8601
04:05:06 ISO 8601
04:05 ISO 8601
040506 ISO 8601
04:05 AM Identique à 04:05 ; AM n'affecte pas la valeur
04:05 PM Identique à 16:05 ; l'heure doit être <= 12
04:05:06.789-8 ISO 8601, avec le décalage UTC comme fuseau horaire
04:05:06-08:00 ISO 8601, avec le décalage UTC comme fuseau horaire
04:05-08:00 ISO 8601, avec le décalage UTC comme fuseau horaire
040506+0730 ISO 8601, avec le décalage UTC avec un fuseau horaire en heure fractionnée
040506+07:30:00 décalage UTC exprimé en secondes (non autorisé dans ISO 8601)
040506-08 ISO 8601
04:05:06 PST fuseau horaire abrégé
2003-04-12 04:05:06 America/New_York fuseau horaire en nom complet

Tableau 8.12. Saisie des fuseaux horaires

Exemple Description
PST Abréviation pour l'heure standard du Pacifique (Pacific Standard Time)
America/New_York Nom complet du fuseau horaire
PST8PDT Nommage POSIX du fuseau horaire
-8:00:00 Décalage UTC pour la zone PST
-8:00 Décalage ISO-8601 pour la zone PST (format étendu ISO 8601)
-800 Décalage ISO-8601 pour la zone PST (format basique ISO 8601)
-8 Décalage ISO-8601 pour la zone PST (format basique ISO 8601)
zulu Abréviation militaire de GMT
z Version courte de zulu (aussi dans ISO 8601)

La Section 8.5.3, « Fuseaux horaires » apporte des précisions quant à la façon d'indiquer les fuseaux horaires.

8.5.1.3. Horodatage

Les saisies valides sont constituées de la concaténation d'une date et d'une heure, éventuellement suivie d'un fuseau horaire et d'un qualificatif AD (après Jésus Christ) ou BC (avant Jésus Christ). (AD/BC peut aussi apparaître avant le fuseau horaire, mais ce n'est pas l'ordre préféré.) Ainsi :

1999-01-08 04:05:06

et :

1999-01-08 04:05:06 -8:00

sont des valeurs valides, qui suivent le standard ISO 8601. Le format très courant :

January 8 04:05:06 1999 PST

est également supporté.

Le standard SQL différencie les libellés timestamp without time zone et timestamp with time zone par la présence d'un symbole « + » ou d'un « - » et le décalage du fuseau horaire après l'indication du temps. De ce fait, d'après le standard,

TIMESTAMP '2004-10-19 10:23:54'

est du type timestamp without time zone alors que

TIMESTAMP '2004-10-19 10:23:54+02'

est du type timestamp with time zone. PostgreSQL™ n'examine jamais le contenu d'un libellé avant de déterminer son type. Du coup, il traite les deux ci-dessus comme des valeurs de type timestamp without time zone. Pour s'assurer qu'un littéral est traité comme une valeur de type timestamp with time zone, il faut préciser explicitement le bon type :

TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02'

Dans un libellé de type timestamp without time zone, PostgreSQL™ ignore silencieusement toute indication de fuseau horaire. C'est-à-dire que la valeur résultante est dérivée des champs date/heure de la valeur saisie et n'est pas corrigée par le fuseau horaire.

Pour timestamp with time zone, la valeur stockée en interne est toujours en UTC (Universal Coordinated Time ou Temps Universel Coordonné), aussi connu sous le nom de GMT (Greenwich Mean Time). Les valeurs saisies avec un fuseau horaire explicite sont converties en UTC à l'aide du décalage approprié. Si aucun fuseau horaire n'est précisé, alors le système considère que la date est dans le fuseau horaire indiqué par le paramètre système TimeZone, et la convertit en UTC en utilisant le décalage de la zone timezone.

Quand une valeur timestamp with time zone est affichée, elle est toujours convertie de l'UTC vers le fuseau horaire courant (variable timezone), et affichée comme une heure locale. Pour voir l'heure dans un autre fuseau horaire, il faut, soit changer la valeur de timezone, soit utiliser la construction AT TIME ZONE (voir la Section 9.9.3, « AT TIME ZONE »).

Les conversions entre timestamp without time zone et timestamp with time zone considèrent normalement que la valeur timestamp without time zone utilise le fuseau horaire timezone. Un fuseau différent peut être choisi en utilisant AT TIME ZONE.

8.5.1.4. Valeurs spéciales

PostgreSQL™ supporte plusieurs valeurs de dates spéciales, dans un souci de simplification. Ces valeurs sont présentées dans le Tableau 8.13, « Saisie de dates/heures spéciales ». Les valeurs infinity et -infinity ont une représentation spéciale dans le système et sont affichées ainsi ; les autres ne sont que des raccourcies de notation convertis en dates/heures ordinaires lorsqu'ils sont lus. (En particulier, now et les chaînes relatives sont converties en une valeur de temps spécifique à leur lecture). Toutes ces valeurs doivent être écrites entre simples quotes lorsqu'elles sont utilisées comme des constantes dans les commandes SQL.

Tableau 8.13. Saisie de dates/heures spéciales

Saisie Types valides Description
epoch date, timestamp 1970-01-01 00:00:00+00 (date système zéro d'Unix)
infinity date, timestamp plus tard que toutes les autres dates
-infinity date, timestamp plus tôt que toutes les autres dates
now date, time, timestamp heure de démarrage de la transaction courante
today date, timestamp aujourd'hui minuit (00:00)
tomorrow date, timestamp demain minuit (00:00)
yesterday date, timestamp hier minuit (00:00)
allballs time 00:00:00.00 UTC

Les fonctions suivantes, compatibles avec le standard SQL, peuvent aussi être utilisées pour obtenir l'heure courante pour le type de données correspondant : CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME, LOCALTIMESTAMP. (Voir la Section 9.9.4, « Date/Heure courante »). Ce sont là des fonctions SQL qui ne sont pas reconnues comme chaînes de saisie de données.

[Attention]

Attention

Bien qu'il n'y ait pas de problèmes à utiliser les chaînes now, today, tomorrow et yesterday dans des commandes SQL interactives, elles peuvent avoir un comportement surprenant quand la commande est sauvegardée pour une exécution ultérieure, par exemple dans des requêtes préparées, des vues ou des fonctions. La châine peut être convertie en une valeur spécifique qui continue à être utilisée bien après qu'elle ne soit éculée. Dans de tels contextes, utilisez plutôt une des fonctions SQL. Par exemple, CURRENT_DATE + 1 est plus sûr que 'tomorrow'::date.

8.5.2. Affichage des dates et heures

Le format de sortie des types date/heure peut être positionné à l'un des quatre formats de date suivants : ISO 8601, SQL (Ingres), traditionnel POSTGRES™ (date au format Unix date) ou German (germanique). Le format par défaut est le format ISO. (Le standard SQL impose l'utilisation du format ISO 8601. Le nom du format d'affichage « SQL » est mal choisi, un accident historique.) Le Tableau 8.14, « Styles d'affichage de date/heure » présente des exemples de chaque format d'affichage. La sortie d'un type date ou time n'est évidemment composée que de la partie date ou heure, comme montré dans les exemples. Néanmoins, le style POSTGRES™ affiche seulement les dates dans le format ISO.

Tableau 8.14. Styles d'affichage de date/heure

Spécification de style Description Exemple
ISO standard SQL ISO 8601 1997-12-17 07:37:16-08
SQL style traditionnel 12/17/1997 07:37:16.00 PST
Postgres style original Wed Dec 17 07:37:16 1997 PST
German style régional 17.12.1997 07:37:16.00 PST

[Note]

Note

ISO 8601 spécifie l'utilisation d'une lettre T en majuscule pour séparer la date et l'heure. PostgreSQL™ accepte ce format en entrée. En sortie, il utilise un espace plutôt qu'un T, comme indiqué ci-dessus. C'est à la fois plus lisible et cohérent avec la RFC 3339 ainsi qu'avec d'autres systèmes de bases de données.

Dans les styles SQL et POSTGRES, les jours apparaissent avant le mois si l'ordre des champs DMY a été précisé, sinon les mois apparaissent avant les jours (voir la Section 8.5.1, « Saisie des dates et heures » pour savoir comment ce paramètre affecte l'interprétation des valeurs en entrée). Le Tableau 8.15, « Convention de présentation des dates » présente des exemples.

Tableau 8.15. Convention de présentation des dates

Valeur de datestyle (style de date) Ordre de saisie Exemple d'affichage
SQL, DMY jour/mois/année 17/12/1997 15:37:16.00 CET
SQL, MDY mois/jour/année 12/17/1997 07:37:16.00 PST
Postgres, DMY jour/mois/année Wed 17 Dec 07:37:16 1997 PST

Dans le style ISO, le fuseau horaire est toujours affiché sous la forme d'un décalage numérique signé de UTC, avec un signe positif utilisé pour les zones à l'est de Greenwich. Le décalage sera affiché sous la forme hh (heures seulement) s'il s'agit d'un nombre intégral d'heures, ou sous la forme hh:mm s'il s'agit d'un nombre intégral de minutes, et enfin sous la forme hh:mm:ss. (Le troisième cas n'est pas possible pour tout standard moderne de fuseau horaire, mais il peut apparaître en travaillant sur des jours antérieurs à l'adoption des fuseaux horaires standardisés.) Pour les autres styles de dates, le fuseau horaire est affiché comme une abréviation alphabétique si l'une d'entre elles est d'utilisation commune dans le fuseau actuel. Sinon, il apparaît comme un décalage numérique signé dans le format basique ISO 8601 (hh ou hhmm).

Le style de date/heure peut être sélectionné à l'aide de la commande SET datestyle, du paramètre datestyle du fichier de configuration postgresql.conf ou par la variable d'environnement PGDATESTYLE sur le serveur ou le client.

La fonction de formatage to_char (voir Section 9.8, « Fonctions de formatage des types de données ») permet de formater les affichages de date/heure de manière plus flexible.

8.5.3. Fuseaux horaires

Les fuseaux horaires et les conventions liées sont influencés par des décisions politiques, pas uniquement par la géométrie de la Terre. Les fuseaux horaires se sont quelque peu standardisés au cours du vingtième siècle, mais continuent à être soumis à des changements arbitraires, particulièrement en respect des règles de changement d'heure (heure d'été/heure d'hiver). PostgreSQL™ utilise la très répandue base de données de fuseaux horaires IANA (Olson) pour gérer les informations sur les règles historiques de fuseau horaire. Pour les dates se situant dans le futur, PostgreSQL™ part de l'assomption que les dernières règles connues pour un fuseau continueront à s'appliquer dans le futur.

PostgreSQL™ se veut compatible avec les définitions standard SQL pour un usage typique. Néanmoins, le standard SQL possède un mélange étrange de types de date/heure et de possibilités. Deux problèmes évidents sont :

  • bien que le type date ne puisse pas se voir associer un fuseau horaire, le type heure peut en avoir un. Les fuseaux horaires, dans le monde réel, ne peuvent avoir de sens qu'associés à une date et à une heure, vu que l'écart peut varier avec l'heure d'été ;

  • le fuseau horaire par défaut est précisé comme un écart numérique constant avec l'UTC. Il n'est, de ce fait, pas possible de s'adapter à l'heure d'été ou d'hiver lorsque l'on fait des calculs arithmétiques qui passent les limites de l'heure d'été et de l'heure d'hiver.

Pour éviter ces difficultés, il est recommandé d'utiliser des types date/heure qui contiennent à la fois une date et une heure lorsque les fuseaux horaires sont utilisés. Il est également préférable de ne pas utiliser le type time with time zone. (Ce type est néanmoins proposé par PostgreSQL™ pour les applications existantes et pour assurer la compatibilité avec le standard SQL.) PostgreSQL™ utilise le fuseau horaire local pour tous les types qui ne contiennent qu'une date ou une heure.

Toutes les dates et heures liées à un fuseau horaire sont stockées en interne en UTC. Elles sont converties en heure locale dans le fuseau indiqué par le paramètre de configuration TimeZone avant d'être affichées sur le client.

PostgreSQL™ permet d'indiquer les fuseaux horaires de trois façons différentes :

  • un nom complet de fuseau horaire, par exemple America/New_York. Les noms reconnus de fuseau horaire sont listés dans la vue pg_timezone_names (voir Section 50.80, « pg_timezone_names »). PostgreSQL™ utilise les données IANA pour cela, les mêmes noms sont donc reconnus par de nombreux autres logiciels ;

  • une abréviation de fuseau horaire, par exemple PST. Une telle indication ne définit qu'un décalage particulier à partir d'UTC, en contraste avec les noms complets de fuseau horaire qui peuvent aussi impliquer un ensemble de dates pour le changement d'heure. Les abréviations reconnues sont listées dans la vue pg_timezone_abbrevs (voir Section 50.79, « pg_timezone_abbrevs »). Les paramètres de configuration TimeZone et log_timezone ne peuvent pas être configurés à l'aide d'une abréviation de fuseau horaire, mais ces abréviations peuvent être utilisées dans les saisies de date/heure et avec l'opérateur AT TIME ZONE ;

  • En plus des noms et abréviations des fuseaux horaires, PostgreSQL™ accepte les spécifications de fuseau horaire du style POSIX, comme décrit dans Section B.5, « Spécification POSIX des fuseaux horaires ». Cette option n'est habituellement pas préférable à utiliser un nom de fuseau horaire, mais cela pourrait se révéler nécessaire si aucune entrée adéquate de fuseau horaire n'est disponible dans la base IANA.

Les abréviations représentent un décalage spécifique depuis UTC, alors qu'un grand nombre des noms complets implique une règle de changement d'heure, et donc potentiellement deux décalages UTC. Par exemple, 2014-06-04 12:00 America/New_York représente minuit à New York, ce qui, pour cette date particulière, sera le fuseau Eastern Daylight Time (UTC-4). Donc 2014-06-04 12:00 EDT stipule ce moment précis. Mais 2014-06-04 12:00 EST représente minuit pour le fuseau Eastern Standard Time (UTC-5), quel que soit le changement d'heure en effet à cette date.

Pour compliquer encore plus, certaines juridictions ont utilisé les mêmes abréviations de fuseau horaire pour signifier des décalages UTC différents. Par exemple, Moscow MSK correspondait à UTC+3 certaines années et UTC+4 à d'autres. PostgreSQL interprète ces abréviations suivant ce à quoi elles correspondent (ou ont correspondu récemment) pour la date indiquée. Mais, comme le montre l'exemple EST ci-dessus, ce n'est pas nécessairement la même chose que l'heure civile locale à ce moment.

Dans tous les cas, les noms et les abréviations des fuseaux horaires sont insensibles à la casse. (C'est un changement par rapport aux versions de PostgreSQL™ antérieures à la 8.2 qui étaient sensibles à la casse dans certains cas et pas dans d'autres.)

Ni les noms ni les abréviations des fuseaux horaires ne sont codés en dur dans le serveur ; ils sont obtenus à partir des fichiers de configuration stockés sous .../share/timezone/ et .../share/timezonesets/ du répertoire d'installation (voir Section B.4, « Fichiers de configuration date/heure »).

Le paramètre de configuration TimeZone peut être fixé dans le fichier postgresql.conf ou par tout autre moyen standard décrit dans le Chapitre 19, Configuration du serveur. Il existe aussi quelques manières spéciales de le configurer :

  • la commande SQL SET TIME ZONE configure le fuseau horaire pour une session. C'est une autre façon d'indiquer SET TIMEZONE TO avec une syntaxe plus compatible avec les spécifications SQL ;

  • la variable d'environnement PGTZ est utilisée par les applications clientes fondées sur libpq pour envoyer une commande SET TIME ZONE au serveur lors de la connexion.

8.5.4. Saisie d'intervalle

Les valeurs de type interval peuvent être saisies en utilisant la syntaxe verbeuse suivante :

[@] quantité
unité [quantité
unité...]
[direction]
     

quantité est un nombre (éventuellement signé) ; unité est microsecond millisecond, second, minute, hour, day, week, month, year, decade, century, millennium, ou des abréviations ou pluriels de ces unités ; direction peut être ago (pour indiquer un intervalle négatif) ou vide. Le signe @ est du bruit optionnel. Les quantités de chaque unité différente sont implicitement ajoutées, avec prise en compte appropriée des signes (+ et -). ago inverse tous les champs. Cette syntaxe est aussi utilisée pour les sorties d'intervalles, si IntervalStyle est positionné à postgres_verbose.

Les quantités de jours, heures, minutes et secondes peuvent être spécifiées sans notations explicites d'unités. Par exemple '1 12:59:10' est comprise comme '1 day 12 hours 59 min 10 sec'. Par ailleurs, une combinaison d'années et de mois peut être spécifiée avec un tiret ; par exemple, '200-10' est compris comme '200 years 10 months'. (Ces formes raccourcies sont en fait les seules autorisées par le standard SQL, et sont utilisées pour la sortie quand la variable IntervalStyle est positionnée à sql_standard.)

Les valeurs d'intervalles peuvent aussi être écrites en tant qu'intervalles de temps ISO 8601, en utilisant soit le « format avec désignateurs » de la section 4.4.3.2 ou le « format alternatif » de la section 4.4.3.3. Le format avec désignateurs ressemble à ceci :

P quantité unité [ quantité unité ...] [ T [ quantité unité ...]]
     

La chaîne doit commencer avec un P, et peut inclure un T qui introduit les unités de ce type. Les abréviations d'unité disponibles sont données dans Tableau 8.16, « Abréviations d'unités d'intervalle ISO 8601 ». Des unités peuvent être omises, et peuvent être spécifiées dans n'importe quel ordre, mais les unités inférieures à un jour doivent apparaître après T. En particulier, la signification de M dépend de son emplacement, c'est-à-dire avant ou après T.

Tableau 8.16. Abréviations d'unités d'intervalle ISO 8601

Abréviation Signification
Y Années
M Mois (dans la zone de date)
W Semaines
D Jours
H Heures
M Minutes (dans la zone de temps)
S Secondes

Dans le format alternatif :

P [ années-mois-jours ] [ T heures:minutes:secondes ]
     

la chaîne doit commencer par P, et un T sépare la zone de date et la zone de temps de l'intervalle. Les valeurs sont données comme des nombres, de façon similaire aux dates ISO 8601.

Lors de l'écriture d'une constante d'intervalle avec une spécification de champs, ou lors de l'assignation d'une chaîne à une colonne d'intervalle qui a été définie avec une spécification de champs, l'interprétation de quantité sans unité dépend des champs. Par exemple, INTERVAL '1' YEAR est interprété comme 1 an, alors que INTERVAL '1' est interprété comme 1 seconde. De plus, les valeurs du champ « à droite » du champ le moins significatif autorisé par la spécification de champs sont annulées de façon silencieuse. Par exemple, écrire INTERVAL '1 day 2:03:04' HOUR TO MINUTE implique la suppression du champ des secondes, mais pas celui des journées.

D'après le standard SQL, toutes les valeurs de tous les champs d'un intervalle doivent avoir le même signe, ce qui entraîne qu'un signe négatif initial s'applique à tous les champs ; par exemple, le signe négatif dans l'expression d'intervalle '-1 2:03:04' s'applique à la fois aux jours et aux heures/minutes/secondes. PostgreSQL™ permet que les champs aient des signes différents, et traditionnellement traite chaque champ de la représentation textuelle comme indépendamment signé, ce qui fait que la partie heure/minute/seconde est considérée comme positive dans l'exemple. Si IntervalStyle est positionné à sql_standard, alors un signe initial est considéré comme s'appliquant à tous les champs (mais seulement si aucun autre signe n'apparaît). Sinon, l'interprétation traditionnelle de PostgreSQL™ est utilisée. Pour éviter les ambiguïtés, il est recommandé d'attacher un signe explicite à chaque partie, si au moins un champ est négatif.

Les valeurs des champs peuvent avoir des parties fractionnelles : par exemple, '1.5 weeks' ou '01:02:03.45'. Néanmoins, comme l'intervalle stocke en interne seulement les trois unités sous forme d'entier (mois, jours, microsecondes), les unités fractionelles doivent être divisées en plus petites unités. Les parties fractionnelles des unités supérieures aux mois est tronquées en un nombre entier de mois, par exemple '1.5 years' devient '1 year 6 mons'. Les parties fractionnelles des semaines et jours sont calculées comme un nombre entier de jours et de microsecondes, en supposant 30 jours par mois et 24 heures par jour, par exemple '1.75 months' devient 1 mon 22 days 12:00:00. Seules les secondes seront affichées en fractionné en sortie.

Tableau 8.17, « Saisie d'intervalle » présente des exemples de saisies d'interval valides.

Tableau 8.17. Saisie d'intervalle

Exemple Description
1-2 Format SQL standard : 1 an 2 mois
3 4:05:06 Format SQL standard : 3 jours 4 heures 5 minutes 6 secondes
1 year 2 months 3 days 4 hours 5 minutes 6 seconds Format PostgreSQL traditionnel : 1 an 2 mois 3 jours 4 heures 5 minutes 6 secondes
P1Y2M3DT4H5M6S « format avec désignateurs » ISO 8601 : signification identique à ci-dessus
P0001-02-03T04:05:06 « format alternatif » ISO 8601 : signification identique à ci-dessus

De façon interne, les valeurs de type interval sont stockées comme mois, jours et microsecondes. C'est ainsi parce que le nombre de jours d'un mois varie, et un jour peut avoir 23 ou 25 heures si des changements d'heures sont impliqués. Les champs mois et jours sont des entiers, alors que le champ microsecondes peut stocker des nombres décimaux. Les intervalles étant habituellement créés à partir de chaînes constantes ou de soustractions de timestamps, cette méthode fonctionne bien dans la plupart des cas, mais peut être la cause de résultats inattendus :

SELECT EXTRACT(hours from '80 minutes'::interval);
 date_part
-----------
         1

SELECT EXTRACT(days from '80 hours'::interval);
 date_part
-----------
         0

Les fonctions justify_days et justify_hours sont disponibles pour ajuster les jours et heures qui dépassent leurs portées habituelles.

8.5.5. Affichage d'intervalles

Le format de sortie du type interval peut être positionné à une de ces quatre valeurs : sql_standard, postgres, postgres_verbose ou iso_8601, en utilisant la commande SET intervalstyle. La valeur par défaut est le format postgres. Tableau 8.18, « Exemples de styles d'affichage d'intervalles » donne des exemples de chaque style de format de sortie.

Le style sql_standard produit une sortie qui se conforme à la spécification du standard SQL pour les chaînes littérales d'intervalle, si la valeur de l'intervalle reste dans les restrictions du standard (soit année-mois seul, ou jour-temps seul, et sans mélanger les composants positifs et négatifs). Sinon, la sortie ressemble au standard littéral année-mois suivi par une chaîne jour-temps littérale, avec des signes explicites ajoutés pour désambiguer les intervalles dont les signes seraient mélangés.

La sortie du style postgres correspond à la sortie des versions de PostgreSQL™ précédant la 8.4, si le paramètre datestyle était positionné à ISO.

La sortie du style postgres_verbose correspond à la sortie des versions de PostgreSQL™ précédant la 8.4, si le paramètre datestyle était positionné à autre chose que ISO.

La sortie du style iso_8601 correspond au « format avec designateurs » décrit dans la section 4.4.3.2 du standard ISO 8601.

Tableau 8.18. Exemples de styles d'affichage d'intervalles

Spécification de style Intervalle année-mois Intervalle date-temps Interval Mixte
sql_standard 1-2 3 4:05:06 -1-2 +3 -4:05:06
postgres 1 year 2 mons 3 days 04:05:06 -1 year -2 mons +3 days -04:05:06
postgres_verbose @ 1 year 2 mons @ 3 days 4 hours 5 mins 6 secs @ 1 year 2 mons -3 days 4 hours 5 mins 6 secs ago
iso_8601 P1Y2M P3DT4H5M6S P-1Y-2M3DT-4H-5M-6S