8.5. Tipos de fecha y hora #

8.5.1. Entrada de fecha y hora
8.5.2. Salida de fecha y hora
8.5.3. Zonas horarias
8.5.4. Entrada de intervalos
8.5.5. Salida de intervalos

PostgreSQL soporta el conjunto completo de tipos de fecha y hora de SQL, que se muestran en la Table 8.9. Las operaciones disponibles en estos tipos de datos se describen en la Section 9.9. Las fechas se cuentan de acuerdo con el calendario gregoriano, incluso en los años anteriores a la introducción de dicho calendario (consulta la Section B.6 para más información).

Table 8.9. Tipos de fecha y hora

NombreTamaño de almacenamientoDescripciónValor mínimoValor máximoResolución
timestamp [ (p) ] [ without time zone ]8 bytestanto fecha como hora (sin zona horaria)4713 a.C.294276 d.C.1 microsegundo
timestamp [ (p) ] with time zone8 bytestanto fecha como hora, con zona horaria4713 a.C.294276 d.C.1 microsegundo
date4 bytesfecha (sin hora del día)4713 a.C.5874897 d.C.1 día
time [ (p) ] [ without time zone ]8 byteshora del día (sin fecha)00:00:0024:00:001 microsegundo
time [ (p) ] with time zone12 byteshora del día (sin fecha), con zona horaria00:00:00+155924:00:00-15591 microsegundo
interval [ fields ] [ (p) ]16 bytesintervalo de tiempo-178000000 años178000000 años1 microsegundo

Note

El estándar SQL requiere que escribir simplemente timestamp sea equivalente a timestamp without time zone, y PostgreSQL respeta ese comportamiento. Se acepta timestamptz como una abreviatura de timestamp with time zone; esta es una extensión de PostgreSQL.

time, timestamp e interval aceptan un valor de precisión opcional p que especifica el número de dígitos fraccionarios retenidos en el campo de los segundos. Por defecto, no hay un límite explícito para la precisión. El rango permitido de p va de 0 a 6.

El tipo interval tiene una opción adicional, que es restringir el conjunto de campos almacenados escribiendo una de estas frases:

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

Ten en cuenta que si se especifican tanto fields como p, los fields deben incluir SECOND, ya que la precisión se aplica solo a los segundos.

El tipo time with time zone está definido por el estándar SQL, pero su definición exhibe propiedades que llevan a una utilidad cuestionable. En la mayoría de los casos, una combinación de date, time, timestamp without time zone y timestamp with time zone debería proporcionar un rango completo de funcionalidad de fecha y hora requerido por cualquier aplicación.

8.5.1. Entrada de fecha y hora #

La entrada de fecha y hora se acepta en casi cualquier formato razonable, incluyendo ISO 8601, compatible con SQL, tradicional de POSTGRES y otros. Para algunos formatos, el orden del día, mes y año en la entrada de fecha es ambiguo y existe soporte para especificar el orden esperado de estos campos. Configura el parámetro DateStyle como MDY para seleccionar la interpretación mes-día-año, DMY para seleccionar la interpretación día-mes-año o YMD para seleccionar la interpretación año-mes-día.

PostgreSQL es más flexible en el manejo de la entrada de fecha y hora de lo que requiere el estándar SQL. Consulta la Appendix B para ver las reglas de análisis exactas de la entrada de fecha y hora y para los campos de texto reconocidos, incluyendo meses, días de la semana y zonas horarias.

Recuerda que cualquier entrada de literal de fecha u hora debe estar encerrada entre comillas simples, como las cadenas de texto. Consulta la Section 4.1.2.7 para obtener más información. SQL requiere la siguiente sintaxis:

tipo [ (p) ] 'valor'

donde p es una especificación de precisión opcional que indica el número de dígitos fraccionarios en el campo de segundos. La precisión se puede especificar para los tipos time, timestamp e interval, y puede variar de 0 a 6. Si no se especifica precisión en una constante, por defecto se toma la precisión del valor literal (pero no más de 6 dígitos).

8.5.1.1. Fechas #

La Table 8.10 muestra algunas posibles entradas para el tipo date.

Table 8.10. Entrada de fechas

EjemploDescripción
1999-01-08ISO 8601; 8 de enero en cualquier modo (formato recomendado)
January 8, 1999no ambiguo en cualquier modo de entrada de datestyle
1/8/19998 de enero en modo MDY; 1 de agosto en modo DMY
1/18/199918 de enero en modo MDY; rechazado en otros modos
01/02/032 de enero de 2003 en modo MDY; 1 de febrero de 2003 en modo DMY; 3 de febrero de 2001 en modo YMD
1999-Jan-088 de enero en cualquier modo
Jan-08-19998 de enero en cualquier modo
08-Jan-19998 de enero en cualquier modo
99-Jan-088 de enero en modo YMD, de lo contrario da error
08-Jan-998 de enero, excepto error en modo YMD
Jan-08-998 de enero, excepto error en modo YMD
19990108ISO 8601; 8 de enero de 1999 en cualquier modo
990108ISO 8601; 8 de enero de 1999 en cualquier modo
1999.008año y día del año
J2451187fecha juliana
January 8, 99 BCaño 99 a.C.

8.5.1.2. Horas #

Los tipos para la hora del día son time [ (p) ] without time zone y time [ (p) ] with time zone. time por sí solo es equivalente a time without time zone.

La entrada válida para estos tipos consiste en una hora del día seguida de una zona horaria opcional. (Consulta la Table 8.11 y la Table 8.12.) Si se especifica una zona horaria en la entrada para time without time zone, esta se ignora silenciosamente. También puedes especificar una fecha pero será ignorada, excepto cuando uses un nombre de zona horaria que implique una regla de horario de verano, como America/New_York. En este caso, especificar la fecha es necesario para determinar si se aplica el horario estándar o el de verano. El desplazamiento de zona horaria apropiado se registra en el valor time with time zone and se devuelve tal como se almacenó; no se ajusta a la zona horaria activa.

Table 8.11. Entrada de hora

EjemploDescripción
04:05:06.789ISO 8601
04:05:06ISO 8601
04:05ISO 8601
040506ISO 8601
04:05 AMigual que 04:05; AM no afecta al valor
04:05 PMigual que 16:05; la hora de entrada debe ser <= 12
04:05:06.789-8ISO 8601, con zona horaria como desplazamiento UTC
04:05:06-08:00ISO 8601, con zona horaria como desplazamiento UTC
04:05-08:00ISO 8601, con zona horaria como desplazamiento UTC
040506-08ISO 8601, con zona horaria como desplazamiento UTC
040506+0730ISO 8601, con zona horaria con fracción de hora como desplazamiento UTC
040506+07:30:00desplazamiento UTC especificado hasta segundos (no permitido en ISO 8601)
04:05:06 PSTzona horaria especificada por abreviatura
2003-04-12 04:05:06 America/New_Yorkzona horaria especificada por nombre completo

Table 8.12. Entrada de zona horaria

EjemploDescripción
PSTAbreviatura (para la hora estándar del Pacífico)
America/New_YorkNombre de zona horaria completo
PST8PDTEspecificación de zona horaria al estilo POSIX
-8:00:00Desplazamiento UTC para PST
-8:00Desplazamiento UTC para PST (formato extendido ISO 8601)
-800Desplazamiento UTC para PST (formato básico ISO 8601)
-8Desplazamiento UTC para PST (formato básico ISO 8601)
zuluAbreviatura militar para UTC
zForma corta de zulu (también en ISO 8601)

Consulta la Section 8.5.3 para obtener más información sobre cómo especificar zonas horarias.

8.5.1.3. Marcas de tiempo (timestamps) #

La entrada válida para los tipos de marcas de tiempo consiste en la concatenación de una fecha y una hora, seguida de una zona horaria opcional, y opcionalmente de AD o BC (a.C./d.C.). (Alternativamente, AD/BC puede aparecer antes de la zona horaria, pero este no es el orden preferido). Así:

1999-01-08 04:05:06

y:

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

son valores válidos, que siguen el estándar ISO 8601. Además, se admite el formato común:

January 8 04:05:06 1999 PST

es soportado.

El estándar SQL diferencia los literales de timestamp without time zone y timestamp with time zone por la presencia de un símbolo + o - y el desplazamiento de zona horaria después de la hora. Por lo tanto, de acuerdo con el estándar,

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

es un timestamp without time zone, mientras que

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

es un timestamp with time zone. PostgreSQL nunca examina el contenido de una cadena literal antes de determinar su tipo, y por lo tanto tratará ambos casos anteriores como timestamp without time zone. Para asegurar que un literal sea tratado como timestamp with time zone, indícale el tipo explícito correcto:

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

En un valor del que se ha determinado que es timestamp without time zone, PostgreSQL ignorará silenciosamente cualquier indicación de zona horaria. Es decir, el valor resultante se deriva de los campos de fecha/hora en la cadena de entrada, y no se ajusta según la zona horaria.

Para los valores timestamp with time zone, una cadena de entrada que incluya una zona horaria explícita se convertirá a UTC (Tiempo Universal Coordinado) utilizando el desplazamiento apropiado para esa zona horaria. Si no se indica ninguna zona horaria en la cadena de entrada, se asume que está en la zona horaria indicada por el parámetro TimeZone del sistema, y se convierte a UTC utilizando el desplazamiento para dicha zona horaria. En cualquier caso, el valor se almacena internamente como UTC, y la zona horaria originalmente declarada o asumida no se conserva.

Cuando se muestra un valor de tipo timestamp with time zone, siempre se convierte de UTC a la zona configurada en timezone, y se muestra como hora local en esa zona. Para ver la hora en otra zona horaria, cambia timezone o usa la construcción AT TIME ZONE (consulta la Section 9.9.4).

Las conversiones entre timestamp without time zone y timestamp with time zone normalmente asumen que el valor timestamp without time zone debe tomarse o entregarse como la hora local de la zona configurada en timezone. Se puede especificar una zona horaria diferente para la conversión utilizando AT TIME ZONE.

8.5.1.4. Valores especiales #

PostgreSQL admite varios valores de entrada especiales de fecha/hora por conveniencia, como se muestra en la Table 8.13. Los valores infinity y -infinity se representan especialmente dentro del sistema y se mostrarán sin cambios; pero los demás son simplemente atajos de notación que se convertirán a valores ordinarios de fecha/hora al leerlos. (En particular, now y las cadenas relacionadas se convierten a un valor de tiempo específico tan pronto como se leen). Todos estos valores deben encerrarse entre comillas simples cuando se usan como constantes en comandos SQL.

Table 8.13. Entradas especiales de fecha/hora

Cadena de entradaTipos válidosDescripción
epochdate, timestamp1970-01-01 00:00:00+00 (el cero del sistema de tiempo Unix)
infinitydate, timestamp, intervalposterior a todas las demás marcas de tiempo
-infinitydate, timestamp, intervalanterior a todas las demás marcas de tiempo
nowdate, time, timestamphora de inicio de la transacción actual
todaydate, timestampmedianoche (00:00) de hoy
tomorrowdate, timestampmedianoche (00:00) de mañana
yesterdaydate, timestampmedianoche (00:00) de ayer
allballstime00:00:00.00 UTC

Las siguientes funciones compatibles con SQL también se pueden usar para obtener el valor de tiempo actual para el tipo de datos correspondiente: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME, LOCALTIMESTAMP. (Consulta la Section 9.9.5.) Ten en cuenta que estas son funciones SQL y no se reconocen en cadenas de entrada de datos.

Caution

Aunque el uso de las cadenas de entrada now, today, tomorrow y yesterday es perfectamente válido en comandos SQL interactivos, pueden tener un comportamiento sorprendente cuando el comando se guarda para ejecutarse más tarde, por ejemplo en sentencias preparadas, vistas y definiciones de funciones. La cadena se puede convertir a un valor de tiempo específico que continúe usándose mucho después de que se haya desactualizado. En su lugar, utiliza una de las funciones SQL en tales contextos. Por ejemplo, CURRENT_DATE + 1 es más seguro que 'tomorrow'::date.

8.5.2. Salida de fecha y hora #

El formato de salida de los tipos de fecha/hora se puede configurar en uno de los cuatro estilos: ISO 8601, SQL (Ingres), tradicional de POSTGRES (formato del comando date de Unix) o alemán. El valor predeterminado es el formato ISO. (El estándar SQL requiere el uso del formato ISO 8601. El nombre del formato de salida SQL es un accidente histórico). La Table 8.14 muestra ejemplos de cada estilo de salida. La salida de los tipos date y time suele ser solo la parte de la fecha o de la hora de acuerdo con los ejemplos mostrados. Sin embargo, el estilo de POSTGRES produce valores de solo fecha en formato ISO.

Table 8.14. Estilos de salida de fecha y hora

Especificación de estiloDescripciónEjemplo
ISOISO 8601, estándar SQL1997-12-17 07:37:16-08
SQLestilo tradicional12/17/1997 07:37:16.00 PST
Postgresestilo originalWed Dec 17 07:37:16 1997 PST
Germanestilo regional17.12.1997 07:37:16.00 PST

Note

ISO 8601 especifica el uso de la letra mayúscula T para separar la fecha y la hora. PostgreSQL acepta ese formato en la entrada, pero en la salida utiliza un espacio en lugar de T, como se muestra arriba. Esto es por legibilidad y consistencia con RFC 3339, así como con otros sistemas de bases de datos.

En los estilos SQL y POSTGRES, el día aparece antes que el mes si se ha especificado el orden de campos DMY; en caso contrario, el mes aparece antes que el día. (Consulta la Section 8.5.1 para ver cómo esta configuración también afecta la interpretación de los valores de entrada). La Table 8.15 muestra ejemplos.

Table 8.15. Convenciones de orden de fecha

Configuración de datestyleOrden de entradaSalida de ejemplo
SQL, DMYdía/mes/año17/12/1997 15:37:16.00 CET
SQL, MDYmes/día/año12/17/1997 07:37:16.00 PST
Postgres, DMYdía/mes/añoWed 17 Dec 07:37:16 1997 PST

En el estilo ISO, la zona horaria siempre se muestra como un desplazamiento numérico con signo desde UTC, utilizando el signo positivo para zonas al este de Greenwich. El desplazamiento se mostrará como hh (solo horas) si es un número entero de horas, de lo contrario como hh:mm si es un número entero de minutos, y como hh:mm:ss en caso contrario. (El tercer caso no es posible con ningún estándar moderno de huso horario, pero puede aparecer al trabajar con marcas de tiempo que son anteriores a la adopción de las zonas horarias estandarizadas). En los otros estilos de fecha, la zona horaria se muestra como una abreviatura alfabética si hay una de uso común en la zona actual. De lo contrario, aparece como un desplazamiento numérico con signo en el formato básico de ISO 8601 (hh o hhmm). Las abreviaturas alfabéticas que se muestran en estos estilos se toman de la entrada de la base de datos de zonas horarias de la IANA seleccionada actualmente por el parámetro de tiempo de ejecución TimeZone; no se ven afectadas por la configuración de timezone_abbreviations.

El estilo de fecha/hora puede ser seleccionado por el usuario mediante el comando SET datestyle, el parámetro DateStyle en el archivo de configuración postgresql.conf o la variable de entorno PGDATESTYLE en el servidor o cliente.

La función de formateo to_char (consulta la Section 9.8) también está disponible como una forma más flexible de dar formato a la salida de fecha y hora.

8.5.3. Zonas horarias #

Las zonas horarias y las convenciones de zona horaria están influenciadas por decisiones políticas, no solo por la geometría de la Tierra. Las zonas horarias de todo el mundo se estandarizaron un poco durante la década de 1900, pero siguen siendo propensas a cambios arbitrarios, particularmente con respecto a las reglas de horario de verano. PostgreSQL utiliza la base de datos de zonas horarias de la IANA (Olson), de uso generalizado, para obtener información sobre las reglas históricas de zonas horarias. Para fechas en el futuro, se asume que las últimas reglas conocidas para una zona horaria determinada se seguirán observando indefinidamente en el futuro.

PostgreSQL se esfuerza por ser compatible con las definiciones del estándar SQL para el uso típico. Sin embargo, el estándar SQL tiene una mezcla extraña de tipos y capacidades de fecha y hora. Dos problemas obvios son:

  • Aunque el tipo date no puede tener una zona horaria asociada, el tipo time sí puede. Las zonas horarias en el mundo real tienen poco sentido a menos que estén asociadas tanto con una fecha como con una hora, ya que el desplazamiento puede variar a lo largo del año con los límites del horario de verano.

  • La zona horaria predeterminada se especifica como un desplazamiento numérico constante de UTC. Por lo tanto, es imposible adaptarse al horario de verano cuando se realiza aritmética de fecha/hora a través de los límites de DST.

Para abordar estas dificultades, recomendamos utilizar tipos de fecha y hora que contengan tanto fecha como hora cuando utilices zonas horarias. No recomendamos utilizar el tipo time with time zone (aunque es compatible con PostgreSQL para aplicaciones heredadas y para el cumplimiento del estándar SQL). PostgreSQL asume tu zona horaria local para cualquier tipo que contenga solo fecha u hora.

Todas las fechas y horas con zona horaria se almacenan internamente en UTC. Se convierten a la hora local en la zona especificada por el parámetro de configuración TimeZone antes de mostrarse al cliente.

PostgreSQL te permite especificar zonas horarias en tres formas diferentes:

  • Un nombre completo de zona horaria, por ejemplo America/New_York. Los nombres de zonas horarias reconocidos se enumeran en la vista pg_timezone_names (consulta la Section 53.34). PostgreSQL utiliza los datos de zonas horarias de la IANA para este propósito, por lo que los mismos nombres de zonas horarias también son reconocidos por otros programas.

  • Una abreviatura de zona horaria, por ejemplo PST. Tal especificación simplemente define un desplazamiento particular de UTC, en contraste con los nombres completos de zonas horarias que también pueden implicar un conjunto de reglas de transición de horario de verano. Las abreviaturas reconocidas se enumeran en la vista pg_timezone_abbrevs (consulta la Section 53.33). No puedes configurar los parámetros de configuración TimeZone o log_timezone con una abreviatura de zona horaria, pero puedes usar abreviaturas en valores de entrada de fecha/hora y con el operador AT TIME ZONE.

  • Además de los nombres y abreviaturas de zonas horarias, PostgreSQL aceptará especificaciones de zona horaria al estilo POSIX, como se describe en la Section B.5. Esta opción normalmente no es preferible a usar una zona horaria con nombre, pero puede ser necesaria si no hay disponible una entrada de zona horaria de la IANA adecuada.

En resumen, esta es la diferencia entre abreviaturas y nombres completos: las abreviaturas representan un desplazamiento específico de UTC, mientras que muchos de los nombres completos implican una regla de horario de verano local, por lo que tienen dos desplazamientos UTC posibles. Como ejemplo, 2014-06-04 12:00 America/New_York representa el mediodía hora local en Nueva York, que para esta fecha en particular era el horario de verano del Este (UTC-4). Así que 2014-06-04 12:00 EDT especifica ese mismo instante de tiempo. Pero 2014-06-04 12:00 EST especifica el mediodía de la hora estándar del Este (UTC-5), independientemente de si el horario de verano estaba nominalmente en efecto en esa fecha.

Note

El signo en las especificaciones de zona horaria al estilo POSIX tiene el significado opuesto al del signo en los valores de fecha y hora ISO-8601. Por ejemplo, la zona horaria POSIX para 2014-06-04 12:00+04 sería UTC-4.

Para complicar las cosas, algunas jurisdicciones han utilizado la misma abreviatura de zona horaria para significar diferentes desplazamientos UTC en diferentes momentos; por ejemplo, en Moscú MSK ha significado UTC+3 en algunos años y UTC+4 en otros. PostgreSQL interpreta tales abreviaturas de acuerdo con lo que significaban (o habían significado más recientemente) en la fecha especificada; pero, al igual que con el ejemplo de EST anterior, esto no es necesariamente lo mismo que la hora civil local en esa fecha.

En todos los casos, los nombres y abreviaturas de zonas horarias se reconocen sin distinguir entre mayúsculas y minúsculas. (Este es un cambio con respecto a las versiones de PostgreSQL anteriores a la 8.2, que distinguían entre mayúsculas y minúsculas en algunos contextos pero no en otros).

Ni los nombres de zonas horarias ni las abreviaturas están integrados en el servidor; se obtienen de archivos de configuración almacenados bajo .../share/timezone/ and .../share/timezonesets/ del directorio de instalación (consulta la Section B.4).

El parámetro de configuración TimeZone se puede configurar en el archivo postgresql.conf, o en cualquiera de las otras formas estándar descritas en la Chapter 19. También hay algunas formas especiales de configurarlo:

  • El comando SQL SET TIME ZONE configura la zona horaria para la sesión. Esta es una ortografía alternativa de SET TIMEZONE TO con una sintaxis más compatible con la especificación SQL.

  • La variable de entorno PGTZ es utilizada por los clientes libpq para enviar un comando SET TIME ZONE al servidor tras la conexión.

8.5.4. Entrada de intervalos #

Los valores de tipo interval se pueden escribir utilizando la siguiente sintaxis detallada:

[@] cantidad unidad [cantidad unidad...] [dirección]

donde cantidad es un número (posiblemente con signo); unidad es microsecond, millisecond, second, minute, hour, day, week, month, year, decade, century, millennium, o abreviaturas o plurales de estas unidades; dirección puede ser ago o vacío. El signo arroba (@) es ruido opcional. Las cantidades de las diferentes unidades se suman implícitamente teniendo en cuenta sus signos. ago niega todos los campos. Esta sintaxis también se utiliza para la salida de intervalos, si IntervalStyle está configurado como postgres_verbose.

Las cantidades de días, horas, minutos y segundos se pueden especificar sin marcas de unidad explícitas. Por ejemplo, '1 12:59:10' se lee igual que '1 day 12 hours 59 min 10 sec'. Además, se puede especificar una combinación de años y meses con un guion; por ejemplo, '200-10' se lee igual que '200 years 10 months'. (De hecho, estas formas más cortas son las únicas permitidas por el estándar SQL, y se utilizan para la salida cuando IntervalStyle está configurado como sql_standard).

Los valores de intervalo también se pueden escribir como intervalos de tiempo ISO 8601, utilizando bien el formato con designadores de la sección 4.4.3.2 del estándar o bien el formato alternativo de la sección 4.4.3.3. El formato con designadores tiene este aspecto:

P cantidad unidad [ cantidad unidad ...] [ T [ cantidad unidad ...]]

La cadena debe comenzar con una P, y puede incluir una T que introduce las unidades de hora del día. Las abreviaturas de unidades disponibles se dan en la Table 8.16. Las unidades se pueden omitir, y se pueden especificar en cualquier orden, pero las unidades menores que un día deben aparecer después de T. En particular, el significado de M depende de si está antes o después de T.

Table 8.16. Abreviaturas de unidades de intervalo ISO 8601

AbreviaturaSignificado
YAños
MMeses (en la parte de la fecha)
WSemanas
DDías
HHoras
MMinutos (en la parte del tiempo)
SSegundos

En el formato alternativo:

P [ años-meses-días ] [ T horas:minutos:segundos ]

la cadena debe comenzar con P, y una T separa las partes de fecha y hora del intervalo. Los valores se dan como números similares a las fechas ISO 8601.

Al escribir una constante de intervalo con una especificación de fields, o al asignar una cadena a una columna de intervalo que fue definida con una especificación de fields, la interpretación de las cantidades sin marcar depende de los fields. Por ejemplo, INTERVAL '1' YEAR se lee como 1 año, mientras que INTERVAL '1' significa 1 segundo. Además, los valores de campo a la derecha del campo menos significativo permitido por la especificación de fields se descartan silenciosamente. Por ejemplo, escribir INTERVAL '1 day 2:03:04' HOUR TO MINUTE da como resultado la eliminación del campo de segundos, pero no del campo de días.

De acuerdo con el estándar SQL, todos los campos de un valor de intervalo deben tener el mismo signo, por lo que un signo negativo inicial se aplica a todos los campos; por ejemplo, el signo negativo en el literal de intervalo '-1 2:03:04' se aplica tanto a los días como a las partes de horas/minutos/segundos. PostgreSQL permite que los campos tengan diferentes signos, y tradicionalmente trata cada campo en la representación textual como firmado independientemente, de modo que la parte de horas/minutos/segundos se considera positiva en este ejemplo. Si IntervalStyle está configurado como sql_standard, se considera que un signo inicial se aplica a todos los campos (pero solo si no aparecen signos adicionales). De lo contrario, se utiliza la interpretación tradicional de PostgreSQL. Para evitar ambigüedades, se recomienda adjuntar un signo explícito a cada campo si algún campo es negativo.

Internamente, los valores de tipo interval se almacenan como tres campos enteros: meses, días y microsegundos. Estos campos se mantienen separados porque el número de días en un mes varía, mientras que un día puede tener 23 o 25 horas si hay una transición de horario de verano de por medio. Una cadena de entrada de intervalo que utiliza otras unidades se normaliza en este formato y luego se reconstruye de manera estandarizada para la salida, por ejemplo:

SELECT '2 years 15 months 100 weeks 99 hours 123456789 milliseconds'::interval;
               interval
---------------------------------------
  3 years 3 mons 700 days 133:17:36.789

Aquí las semanas, que se entienden como 7 días, se han mantenido separadas, mientras que las unidades de tiempo más pequeñas y más grandes se combinaron y normalizaron.

Los valores de los campos de entrada pueden tener partes fraccionarias, por ejemplo '1.5 weeks' o '01:02:03.45'. Sin embargo, debido a que interval almacena internamente solo campos enteros, los valores fraccionarios deben convertirse a unidades más pequeñas. Las partes fraccionarias de unidades mayores que meses se redondean para ser un número entero de meses, por ejemplo, '1.5 years' se convierte en '1 year 6 mons'. Las partes fraccionarias de semanas y días se calculan para ser un número entero de días y microsegundos, asumiendo 30 days por mes y 24 horas por día, por ejemplo, '1.75 months' se convierte en 1 mon 22 days 12:00:00. Solo los segundos se mostrarán como fraccionarios en la salida.

La Table 8.17 muestra algunos ejemplos de entrada de interval válida.

Table 8.17. Entrada de intervalos

EjemploDescripción
1-2formato estándar SQL: 1 año 2 meses
3 4:05:06formato estándar SQL: 3 días 4 horas 5 minutos 6 segundos
1 year 2 months 3 days 4 hours 5 minutes 6 secondsformato tradicional de Postgres: 1 año 2 meses 3 días 4 horas 5 minutos 6 segundos
P1Y2M3DT4H5M6SISO 8601 formato con designadores: mismo significado que el anterior
P0001-02-03T04:05:06ISO 8601 formato alternativo: mismo significado que el anterior

8.5.5. Salida de intervalos #

Como se explicó anteriormente, PostgreSQL almacena los valores de tipo interval como meses, días y microsegundos. Para la salida, el campo de meses se convierte a años y meses dividiendo por 12. El campo de días se muestra tal cual. El campo de microsegundos se convierte a horas, minutos, segundos y fracción de segundos. Por lo tanto, los meses, minutos y segundos nunca se mostrarán excediendo los rangos 0–11, 0–59 y 0–59 respectivamente, mientras que los campos mostrados de años, días y horas pueden ser bastante grandes. (Las funciones justify_days y justify_hours se pueden usar si es conveniente trasladar valores grandes de días u horas al siguiente campo superior).

El formato de salida del tipo de intervalo se puede configurar en uno de los cuatro estilos: sql_standard, postgres, postgres_verbose o iso_8601, usando el comando SET intervalstyle. El valor predeterminado es el formato postgres. La Table 8.18 muestra ejemplos de cada estilo de salida.

El estilo sql_standard produce una salida que se ajusta a la especificación del estándar SQL para cadenas de literales de intervalo, si el valor del intervalo cumple con las restricciones del estándar (bien solo año-mes o bien solo día-tiempo, sin mezclar componentes positivos y negativos). De lo contrario, la salida parece una cadena literal estándar de año-mes seguida de una cadena literal de día-tiempo, con signos explícitos agregados para eliminar la ambigüedad en intervalos con signos mixtos.

La salida del estilo postgres coincide con la salida de las versiones de PostgreSQL anteriores a la 8.4 cuando el parámetro DateStyle estaba configurado en ISO.

La salida del estilo postgres_verbose coincide con la salida de las versiones de PostgreSQL anteriores a la 8.4 cuando el parámetro DateStyle estaba configurado en una salida distinta de ISO.

La salida del estilo iso_8601 coincide con el formato con designadores descrito en la sección 4.4.3.2 del estándar ISO 8601.

Table 8.18. Ejemplos de estilos de salida de intervalos

Especificación de estiloIntervalo año-mesIntervalo día-tiempoIntervalo mixto
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-2M3D​T-4H-5M-6S