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
| Nombre | Tamaño de almacenamiento | Descripción | Valor mínimo | Valor máximo | Resolución |
|---|---|---|---|---|---|
timestamp [ ( | 8 bytes | tanto fecha como hora (sin zona horaria) | 4713 a.C. | 294276 d.C. | 1 microsegundo |
timestamp [ ( | 8 bytes | tanto fecha como hora, con zona horaria | 4713 a.C. | 294276 d.C. | 1 microsegundo |
date | 4 bytes | fecha (sin hora del día) | 4713 a.C. | 5874897 d.C. | 1 día |
time [ ( | 8 bytes | hora del día (sin fecha) | 00:00:00 | 24:00:00 | 1 microsegundo |
time [ ( | 12 bytes | hora del día (sin fecha), con zona horaria | 00:00:00+1559 | 24:00:00-1559 | 1 microsegundo |
interval [ | 16 bytes | intervalo de tiempo | -178000000 años | 178000000 años | 1 microsegundo |
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.
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).
La Table 8.10 muestra algunas posibles
entradas para el tipo date.
Table 8.10. Entrada de fechas
| Ejemplo | Descripción |
|---|---|
| 1999-01-08 | ISO 8601; 8 de enero en cualquier modo (formato recomendado) |
| January 8, 1999 | no ambiguo en cualquier modo de entrada de datestyle |
| 1/8/1999 | 8 de enero en modo MDY;
1 de agosto en modo DMY |
| 1/18/1999 | 18 de enero en modo MDY;
rechazado en otros modos |
| 01/02/03 | 2 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-08 | 8 de enero en cualquier modo |
| Jan-08-1999 | 8 de enero en cualquier modo |
| 08-Jan-1999 | 8 de enero en cualquier modo |
| 99-Jan-08 | 8 de enero en modo YMD, de lo contrario da error |
| 08-Jan-99 | 8 de enero, excepto error en modo YMD |
| Jan-08-99 | 8 de enero, excepto error en modo YMD |
| 19990108 | ISO 8601; 8 de enero de 1999 en cualquier modo |
| 990108 | ISO 8601; 8 de enero de 1999 en cualquier modo |
| 1999.008 | año y día del año |
| J2451187 | fecha juliana |
| January 8, 99 BC | año 99 a.C. |
Los tipos para la hora del día son time [
( y
p) ] without time zonetime [ (. p) ] with time
zonetime 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
| Ejemplo | Descripción |
|---|---|
04:05:06.789 | ISO 8601 |
04:05:06 | ISO 8601 |
04:05 | ISO 8601 |
040506 | ISO 8601 |
04:05 AM | igual que 04:05; AM no afecta al valor |
04:05 PM | igual que 16:05; la hora de entrada debe ser <= 12 |
04:05:06.789-8 | ISO 8601, con zona horaria como desplazamiento UTC |
04:05:06-08:00 | ISO 8601, con zona horaria como desplazamiento UTC |
04:05-08:00 | ISO 8601, con zona horaria como desplazamiento UTC |
040506-08 | ISO 8601, con zona horaria como desplazamiento UTC |
040506+0730 | ISO 8601, con zona horaria con fracción de hora como desplazamiento UTC |
040506+07:30:00 | desplazamiento UTC especificado hasta segundos (no permitido en ISO 8601) |
04:05:06 PST | zona horaria especificada por abreviatura |
2003-04-12 04:05:06 America/New_York | zona horaria especificada por nombre completo |
Table 8.12. Entrada de zona horaria
| Ejemplo | Descripción |
|---|---|
PST | Abreviatura (para la hora estándar del Pacífico) |
America/New_York | Nombre de zona horaria completo |
PST8PDT | Especificación de zona horaria al estilo POSIX |
-8:00:00 | Desplazamiento UTC para PST |
-8:00 | Desplazamiento UTC para PST (formato extendido ISO 8601) |
-800 | Desplazamiento UTC para PST (formato básico ISO 8601) |
-8 | Desplazamiento UTC para PST (formato básico ISO 8601) |
zulu | Abreviatura militar para UTC |
z | Forma 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.
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.
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 entrada | Tipos válidos | Descripción |
|---|---|---|
epoch | date, timestamp | 1970-01-01 00:00:00+00 (el cero del sistema de tiempo Unix) |
infinity | date, timestamp, interval | posterior a todas las demás marcas de tiempo |
-infinity | date, timestamp, interval | anterior a todas las demás marcas de tiempo |
now | date, time, timestamp | hora de inicio de la transacción actual |
today | date, timestamp | medianoche (00:00) de hoy |
tomorrow | date, timestamp | medianoche (00:00) de mañana |
yesterday | date, timestamp | medianoche (00:00) de ayer |
allballs | time | 00: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.
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.
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 estilo | Descripción | Ejemplo |
|---|---|---|
ISO | ISO 8601, estándar SQL | 1997-12-17 07:37:16-08 |
SQL | estilo tradicional | 12/17/1997 07:37:16.00 PST |
Postgres | estilo original | Wed Dec 17 07:37:16 1997 PST |
German | estilo regional | 17.12.1997 07:37:16.00 PST |
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 datestyle | Orden de entrada | Salida de ejemplo |
|---|---|---|
SQL, DMY | día/mes/año | 17/12/1997 15:37:16.00 CET |
SQL, MDY | mes/día/año | 12/17/1997 07:37:16.00 PST |
Postgres, DMY | día/mes/año | Wed 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.
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.
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.
Los valores de tipo interval se pueden escribir utilizando la siguiente
sintaxis detallada:
[@]cantidadunidad[cantidadunidad...] [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:
Pcantidadunidad[cantidadunidad...] [ T [cantidadunidad...]]
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
| Abreviatura | Significado |
|---|---|
| Y | Años |
| M | Meses (en la parte de la fecha) |
| W | Semanas |
| D | Días |
| H | Horas |
| M | Minutos (en la parte del tiempo) |
| S | Segundos |
En el formato alternativo:
P [años-meses-días] [ Thoras: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
| Ejemplo | Descripción |
|---|---|
1-2 | formato estándar SQL: 1 año 2 meses |
3 4:05:06 | formato estándar SQL: 3 días 4 horas 5 minutos 6 segundos |
1 year 2 months 3 days 4 hours 5 minutes 6 seconds | formato tradicional de Postgres: 1 año 2 meses 3 días 4 horas 5 minutos 6 segundos |
P1Y2M3DT4H5M6S | ISO 8601 “formato con designadores”: mismo significado que el anterior |
P0001-02-03T04:05:06 | ISO 8601 “formato alternativo”: mismo significado que el anterior |
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 estilo | Intervalo año-mes | Intervalo día-tiempo | Intervalo mixto |
|---|---|---|---|
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 |