PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 12.18 » Langage SQL » Types de données » Types date/heure

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. Les opérations disponibles sur ces types de données sont décrites dans la Section 9.9. 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 pour plus d'informations).

Tableau 8.9. Types date et heure

NomTaille de stockageDescriptionValeur minimaleValeur maximaleRésolution
timestamp [ (p) ] [ without time zone ]8 octetsdate et heure (sans fuseau horaire)4713 avant JC294276 après JC1 microseconde
timestamp [ (p) ] with time zone8 octetsdate et heure, avec fuseau horaire4713 avant JC294276 après JC1 microseconde
date4 octetsdate seule (pas d'heure)4713 avant JC5874897 après JC1 jour
time [ (p) ] [ without time zone ]8 octetsheure seule (pas de date)00:00:00.0024:00:001 microseconde
time [ (p) ] with time zone12 octetsheure (sans date), avec fuseau horaire00:00:00+155924:00:00-15591 microseconde
interval [ champs ] [ (p) ]16 octetsintervalles de temps-178000000 années178000000 années1 microseconde

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.

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.

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 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 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 spécifiée pour les types time, timestamp et interval, et peut aller de 0 à 6. Si aucune précision n'est indiquée dans une déclaration de constante, celle de la valeur littérale est utilisée (mais pas plus de 6 chiffres).

8.5.1.1. Dates

Le Tableau 8.10 regroupe les formats de date possibles pour la saisie de valeurs de type date.

Tableau 8.10. Saisie de date

ExempleDescription
1999-01-08ISO-8601 ; 8 janvier, quel que soit le mode (format recommandé)
January 8, 1999sans ambiguïté quel que soit le style de date (datestyle)
1/8/19998 janvier en mode MDY ; 1er août en mode DMY
1/18/199918 janvier en mode MDY ; rejeté dans les autres modes
01/02/032 janvier 2003 en mode MDY ; 1er février 2003 en mode DMY ; 3 février 2001 en mode YMD
1999-Jan-088 janvier dans tous les modes
Jan-08-19998 janvier dans tous les modes
08-Jan-19998 janvier dans tous les modes
99-Jan-088 janvier en mode YMD, erreur sinon
08-Jan-998 janvier, sauf en mode YMD : erreur
Jan-08-998 janvier, sauf en mode YMD : erreur
19990108ISO-8601 ; 8 janvier 1999 dans tous les modes
990108ISO-8601 ; 8 janvier 1999 dans tous les modes
1999.008Année et jour de l'année
J2451187Date du calendrier Julien
January 8, 99 BCAnné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 et le Tableau 8.12). 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 et est affiché de la façon dont il est stocké ; il n'est pas converti vers le fuseau horaire actif.

Tableau 8.11. Saisie d'heure

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

Tableau 8.12. Saisie des fuseaux horaires

ExempleDescription
PSTAbréviation pour l'heure standard du Pacifique (Pacific Standard Time)
America/New_YorkNom complet du fuseau horaire
PST8PDTNommage POSIX du fuseau horaire
-8:00:00Décalage UTC pour la zone PST
-8:00Décalage ISO-8601 pour la zone PST (format étendu ISO 8601)
-800Décalage ISO-8601 pour la zone PST (format basique ISO 8601)
-8Décalage ISO-8601 pour la zone PST (format basique ISO 8601)
zuluAbréviation militaire de GMT
zVersion courte de zulu (aussi dans ISO 8601)

La Section 8.5.3 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).

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. 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

SaisieTypes validesDescription
epochdate, timestamp1970-01-01 00:00:00+00 (date système zéro d'Unix)
infinitydate, timestampplus tard que toutes les autres dates
-infinitydate, timestampplus tôt que toutes les autres dates
nowdate, time, timestampheure de démarrage de la transaction courante
todaydate, timestampaujourd'hui minuit (00:00)
tomorrowdate, timestampdemain minuit (00:00)
yesterdaydate, timestamphier minuit (00:00)
allballstime00: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). Ce sont là des fonctions SQL qui ne sont pas reconnues comme chaînes de saisie de données.

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 chaîne peut être convertie en une valeur spécifique qui continue à être utilisée bien après qu'elle ne soit obsolète. 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 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 styleDescriptionExemple
ISOstandard SQL ISO 86011997-12-17 07:37:16-08
SQLstyle traditionnel12/17/1997 07:37:16.00 PST
Postgresstyle originalWed Dec 17 07:37:16 1997 PST
Germanstyle régional17.12.1997 07:37:16.00 PST

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 pour savoir comment ce paramètre affecte l'interprétation des valeurs en entrée). Le Tableau 8.15 présente des exemples.

Tableau 8.15. Convention de présentation des dates

Valeur de datestyle (style de date)Ordre de saisieExemple d'affichage
SQL, DMYjour/mois/année17/12/1997 15:37:16.00 CET
SQL, MDYmois/jour/année12/17/1997 07:37:16.00 PST
Postgres, DMYjour/mois/annéeWed 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) 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 51.92). 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 51.91). 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. 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).

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. 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. 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éviationSignification
YAnnées
MMois (dans la zone de date)
WSemaines
DJours
HHeures
MMinutes (dans la zone de temps)
SSecondes

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 présente des exemples de saisies d'interval valides.

Tableau 8.17. Saisie d'intervalle

ExempleDescription
1-2Format SQL standard : 1 an 2 mois
3 4:05:06Format SQL standard : 3 jours 4 heures 5 minutes 6 secondes
1 year 2 months 3 days 4 hours 5 minutes 6 secondsFormat 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

En interne, les valeurs interval sont enregistrées comme des mois, jours et microsecondes. C'est fait ainsi parce que le nombre de jours dans un mois varie, et un jour peut avoir 23 ou 25 heures s'il y a eu un changement d'heure. Les champs mois et jours sont des entiers, alors que le champ des microsecondes peut contenir des secondes fractionnelles. Comme les intervalles sont habituellement créés à partir de chaînes constantes ou de soustractions de timestamp, cette méthode de stockage 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 l'étendue normale.

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 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 styleIntervalle année-moisIntervalle date-tempsInterval Mixte
sql_standard1-23 4:05:06-1-2 +3 -4:05:06
postgres1 year 2 mons3 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_8601P1Y2MP3DT4H5M6SP-1Y-2M3DT-4H-5M-6S