# Tipos temporales (Parte 1)

## Introduction

MobilityDB proporciona varios tipos temporales basados ​​en tipos PostgreSQL o PostGIS, a saber, `tbool`, `tint`, `tfloat`, `ttext`, `tgeometry`, `tgeography`, `tgeompoint` y `tgeogpoint`, que se basan, respectivamente, en los tipos de base `bool`, `integer`, `float`, `text`, `geometry` y `geography`, donde `tgeometry` y `tgeography` aceptan geometrías/geografías arbitrarias, mientras que `tgeompoint` y `tgeogpoint` solo aceptan puntos 2D o 3D con dimensión Z. Además, MobilityDB proporciona otros tipos espaciales específicos, a saber, `cbuffer` (buffer circular), `npoint` (punto de red) y `pose`, y sus tipos espaciotemporales correspondientes, a saber, `tcbuffer`, `tnpoint`, `tpose` y `trgeometry` (geometría rígida temporal). En este capítulo y en el siguiente, presentamos las funciones y operadores disponibles para todos los tipos temporales, mientras que las funciones específicas para los tipos espaciotemporales se detallarán en capítulos posteriores.

La interpolación de un valor temporal establece cómo evoluciona el valor entre instantes sucesivos. La interpolación es discreta cuando se desconoce el valor entre dos instantes sucesivos. Pueden representar, por ejemplo, entradas/salidas cuando se utiliza un lector de tarjetas RFID para entrar o salir de un edificio. La interpolación es escalonada cuando el valor permanece constante entre dos instantes sucesivos. Por ejemplo, la marcha que utiliza un automóvil en movimiento puede representarse con un número entero temporal, lo que indica que su valor es constante entre dos instantes de tiempo. Por otro lado, la interpolación es lineal cuando el valor evoluciona linealmente entre dos instantes sucesivos. Por ejemplo, la velocidad de un automóvil puede representarse con un flotante temporal, lo que indica que los valores se conocen en los instantes de tiempo pero evolucionan continuamente entre ellos. De manera similar, la ubicación de un vehículo se puede representar mediante un punto temporal en el que la ubicación entre dos lecturas GPS consecutivas se obtiene mediante interpolación lineal. Los tipos temporales basados en tipos base discretos, es decir `tbool`, `tint` o `ttext` evolucionan necesariamente de manera escalonada. Por otro lado, los tipos temporales basados en tipos base continuos, es decir `tfloat`, `tgeompoint` o `tgeogpoint` pueden evolucionar de manera lineal o escalonada. Nótese que los tipos `tgeometry` y `tgeography` solo admiten interpolación discreta o por escalonada, ya que no es posible interpolar linealmente dos geometrías/geografías arbitrarias.

El subtipo de un valor temporal establece la extensión temporal en la que se registra la evolución de los valores. Los valores temporales vienen en tres subtipos, explicados a continuación.

Un valor temporal de subtipo instante (brevemente, un valor de instante) representa el valor en un instante de tiempo, por ejemplo

    SELECT tfloat '17@2018-01-01 08:00:00';

Un valor temporal de subtipo secuencia (brevemente, un valor de secuencia) representa la evolución del valor durante una secuencia de instantes de tiempo, donde los valores entre estos instantes se interpolan usando una función discreta, escalonada, o lineal (ver arriba). Un ejemplo es el siguiente:

    -- Interpolación discreta
    SELECT tfloat '{17@2018-01-01 08:00:00, 17.5@2018-01-01 08:05:00, 18@2018-01-01 08:10:00}';
    -- Interpolación escalonada
    SELECT tfloat 'Interp=Step;(10@2018-01-01 08:00:00, 20@2018-01-01 08:05:00,
      15@2018-01-01 08:10:00]';
    -- Interpolación lineal
    SELECT tfloat '(10@2018-01-01 08:00:00, 20@2018-01-01 08:05:00, 15@2018-01-01 08:10:00]';

Como puede verse, un valor de secuencia tiene un límite superior e inferior que pueden ser inclusivos (representados por ‘`[`’ y ‘`]`’) o exclusivos (representados por ‘`(`' y ‘`)`'). Por definición, ambos límites deben ser inclusivos cuando la interpolación es discreta o cuando la secuencia tiene un solo instante (que se llama secuencia instantánea), como el ejemplo suiguiente.

    SELECT tint '[10@2018-01-01 08:00:00]';

Los valores de secuencia deben ser uniformes, es decir, deben construirse a partir de valores de instante del mismo tipo de base. Los valores de secuencia con interpolación escalonada o lineal se denominan secuencias continuas.

El valor de una secuencia temporal se interpreta asumiendo que el período de tiempo definido por cada par de valores consecutivos `v1@t1` y `v2@t2` es inferior inclusivo y superior exclusivo, a menos que sean el primer o el último instantes de la secuencia y, en ese caso, se aplican los límites de toda la secuencia. Además, el valor que toma la secuencia temporal entre dos instantes consecutivos depende de si la interpolación es escalonada o lineal. Por ejemplo, la secuencia temporal anterior representa que el valor es `10` durante`(2018-01-01 08:00:00, 2018-01-01 08:05:00)`, `20` durante `[2018-01-01 08:05:00, 2018-01-01 08:10:00)` y `15` en el instante final `2018-01-01 08:10:00`. Por otro lado, la siguiente secuencia temporal

    SELECT tfloat '(10@2018-01-01 08:00:00, 20@2018-01-01 08:05:00, 15@2018-01-01 08:10:00]';

representa que el valor evoluciona linealmente de `10` a `20` durante `(2018-01-01 08:00:00, 2018-01-01 08:05:00)` y evoluciona de `20` a `15` durante `[2018-01-01 08:05:00, 2018-01-01 08:10:00]`.

Finalmente, un valor temporal de subtipo conjunto de secuencias (brevemente, un valor de conjunto de secuencias) representa la evolución del valor en un conjunto de secuencias, donde se desconocen los valores entre estas secuencias. Un ejemplo es el siguiente:

    SELECT tfloat '{[17@2018-01-01 08:00:00, 17.5@2018-01-01 08:05:00],
      [18@2018-01-01 08:10:00, 18@2018-01-01 08:15:00]}';

Como se muestra en los ejemplos anteriores, los valores de conjunto de secuencias solo pueden ser de interpolación escalonada o lineal. Además, todas las secuencias que componen un valor de conjunto de secuencias deben ser del mismo tipo de base y de la misma interpolación.

Los valores de secuencia continuos se convierten en forma normal de modo que los valores equivalentes tengan representaciones idénticas. Para ello, los valores de instante consecutivos se fusionan cuando es posible. Para la interpolación escalonada, tres valores instantáneos consecutivos se pueden fusionar en dos si tienen el mismo valor. Para la interpolación lineal, tres valores instantáneos consecutivos se pueden fusionar en dos si las funciones lineales que definen la evolución de los valores son las mismas. Ejemplos de transformación en forma normal son los siguientes.

    SELECT tint '[1@2001-01-01, 2@2001-01-03, 2@2001-01-04, 2@2001-01-05)';
    -- [1@2001-01-01 00:00:00+00, 2@2001-01-03 00:00:00+00, 2@2001-01-05 00:00:00+00)
    SELECT asText(tgeompoint '[Point(1 1)@2001-01-01 08:00:00, Point(1 1)@2001-01-01 08:05:00,
      Point(1 1)@2001-01-01 08:10:00)');
    -- [Point(1 1)@2001-01-01 08:00:00, Point(1 1)@2001-01-01 08:10:00)
    SELECT tfloat '[1@2001-01-01, 2@2001-01-03, 3@2001-01-05]';
    -- [1@2001-01-01 00:00:00+00, 3@2001-01-05 00:00:00+00]
    SELECT asText(tgeompoint '[Point(1 1)@2001-01-01 08:00:00, Point(2 2)@2001-01-01 08:05:00,
      Point(3 3)@2001-01-01 08:10:00]');
    -- [Point(1 1)@2001-01-01 08:00:00, Point(3 3)@2001-01-01 08:10:00]

De manera similar, los valores del conjunto de secuencias temporales se convierten en forma normal. Para ello, los valores de secuencia consecutivos se fusionan cuando es posible. Ejemplos de transformación en forma normal son los siguientes.

    SELECT tint '{[1@2001-01-01, 1@2001-01-03), [2@2001-01-03, 2@2001-01-05)}';
    -- '{[1@2001-01-01 00:00:00+00, 2@2001-01-03 00:00:00+00, 2@2001-01-05 00:00:00+00)}'
    SELECT tfloat '{[1@2001-01-01, 2@2001-01-03), [2@2001-01-03, 3@2001-01-05]}';
    -- '{[1@2001-01-01 00:00:00+00, 3@2001-01-05 00:00:00+00]}'
    SELECT tfloat '{[1@2001-01-01, 3@2001-01-05), [3@2001-01-05]}';
    -- '{[1@2001-01-01 00:00:00+00, 3@2001-01-05 00:00:00+00]}'
    SELECT asText(tgeompoint '{[Point(0 0)@2001-01-01 08:00:00,
      Point(1 1)@2001-01-01 08:05:00, Point(1 1)@2001-01-01 08:10:00),
      [Point(1 1)@2001-01-01 08:10:00, Point(1 1)@2001-01-01 08:15:00)}');
    /* {[[Point(0 0)@2001-01-01 08:00:00, Point(1 1)@2001-01-01 08:05:00,
       Point(1 1)@2001-01-01 08:15:00)} */
    SELECT asText(tgeompoint '{[Point(1 1)@2001-01-01 08:00:00,Point(2 2)@2001-01-01 08:05:00),
      [Point(2 2)@2001-01-01 08:05:00, Point(3 3)@2001-01-01 08:10:00]}');
    -- {[Point(1 1)@2001-01-01 08:00:00, Point(3 3)@2001-01-01 08:10:00]}
    SELECT asText(tgeompoint '{[Point(1 1)@2001-01-01 08:00:00,Point(3 3)@2001-01-01 08:10:00),
      [Point(3 3)@2001-01-01 08:10:00]}');
    -- {[Point(1 1)@2001-01-01 08:00:00, Point(3 3)@2001-01-01 08:10:00]}

Los tipos temporales soportan modificadores de typo (o `typmod` en terminología de PostgreSQL), que especifican información adicional para la definición de una columna. Por ejemplo, en la siguiente definición de tabla:

    CREATE TABLE Department(DeptNo integer, DeptName varchar(25), NoEmps tint(Sequence));

el modificador de tipo para el tipo `varchar` es el valor 25, que indica la longitud máxima de los valores de la columna, mientras que el modificador de tipo para el tipo `tint` es la cadena de caracteres `Sequence`, que restringe el subtipo de los valores de la columna para que sean secuencias. En el caso de tipos alfanuméricos temporales (es decir, `tbool`, `tint`, `tfloat` y `ttext`), los valores posibles para el modificador de tipo son `Instant`, `Sequence` y `SequenceSet`. Si no se especifica ningún modificador de tipo para una columna, se permiten valores de cualquier subtipo.

Por otro lado, en el caso de tipos de puntos temporales (es decir, `tgeompoint` o `tgeogpoint`) el modificador de tipo se puede utilizar para especificar el subtipo, la dimensionalidad y/o el identificador de referencia espacial (SRID). Por ejemplo, en la siguiente definición de tabla:

    CREATE TABLE Flight(FlightNo integer, Route tgeogpoint(Sequence, PointZ, 4326));

el modificador de typo para el tipo `tgeogpoint` se compone de tres valores, el primero indica el subtipo como arriba, el segundo el tipo espacial de las geografías que componen el punto temporal y el último el SRID de las geografías que componen. Para los puntos temporales, los valores posibles para el primer argumento del modificador de tipo son los anteriores, los del segundo argumento son `Point` o `PointZ` y los del tercer argumento son SRID válidos. Los tres argumentos son opcionales y si alguno de ellos no se especifica para una columna, se permiten valores de cualquier subtipo, dimensionalidad y/o SRID.

Cada tipo temporal está asociado a otro tipo, conocido como su cuadro delimitador, que representan su extensión en la dimensión de valor y/o tiempo. El cuadro delimitador de los distintos tipos temporales es el siguiente:

- El tipo `tstzspan` para los tipos `tbool` y `ttext`, donde solo se considera la extensión temporal.

- El tipo `tbox` (temporal box) par los tipos `tint` y `tfloat`, donde la extensión del valor y de tiempo se define, respectivamente, por un rango numérico y un rango de tiempo.

- El tipo `stbox` (spatiotemporal box) para los tipos `tgeompoint` y `tgeogpoint`, donde la extensión espacial se define en las dimensiones X, Y y Z y la extensión de timpo se define en un rango de tiempo.

Un amplio conjunto de funciones y operadores son disponibles para realizar varias operaciones en los tipos temporales. Estos se explican a continuación y en los próximos capítulos. Algunas de estas operaciones, en particular las relacionadas con índices, manipulan cuadros delimitadores por razones de eficiencia.

## Ejemplos de tipos temporales

A continuación se dan ejemplos de uso de tipos alfanuméricos temporales.

    CREATE TABLE Department(DeptNo integer, DeptName varchar(25), NoEmps tint);
    INSERT INTO Department VALUES
      (10, 'Research', tint '[10@2001-01-01, 12@2001-04-01, 12@2001-08-01)'),
      (20, 'Human Resources', tint '[4@2001-02-01, 6@2001-06-01, 6@2001-10-01)');
    CREATE TABLE Temperature(RoomNo integer, Temp tfloat);
    INSERT INTO Temperature VALUES
      (1001, tfloat '{18.5@2001-01-01 08:00:00, 20.0@2001-01-01 08:10:00}'),
      (2001, tfloat '{19.0@2001-01-01 08:00:00, 22.5@2001-01-01 08:10:00}');

    -- Valor en una marca de tiempo
    SELECT RoomNo, valueAtTimestamp(Temp, '2001-01-01 08:10:00')
    FROM temperature;
    -- 1001 | 20
    -- 2001 | 22.5

    -- Restricción a un valor
    SELECT DeptNo, atValues(NoEmps, 10)
    FROM Department;
    -- 10 | [10@2001-01-01, 10@2001-04-01)
    -- 20 |

    -- Restricción a un período
    SELECT DeptNo, atTime(NoEmps, tstzspan '[2001-01-01, 2001-04-01]')
    FROM Department;
    -- 10 | [10@2001-01-01, 12@2001-04-01]
    -- 20 | [4@2001-02-01, 4@2001-04-01]

    -- Comparación temporal
    SELECT DeptNo, NoEmps #<= 10
    FROM Department;
    -- 10 | [t@2001-01-01, f@2001-04-01, f@2001-08-01)
    -- 20 | [t@2001-02-01, t@2001-10-01)

    -- Agregación temporal
    SELECT tsum(NoEmps)
    FROM Department;
    /* {[10@2001-01-01, 14@2001-02-01, 16@2001-04-01,
       18@2001-06-01, 6@2001-08-01, 6@2001-10-01)} */

A continuación se dan ejemplos de uso de tipos de puntos temporales.

    CREATE TABLE Trips(CarId integer, TripId integer, Trip tgeompoint);
    INSERT INTO Trips VALUES
      (10, 1, tgeompoint '{[Point(0 0)@2001-01-01 08:00:00, Point(2 0)@2001-01-01 08:10:00,
    Point(2 1)@2001-01-01 08:15:00)}'),
      (20, 1, tgeompoint '{[Point(0 0)@2001-01-01 08:05:00, Point(1 1)@2001-01-01 08:10:00,
      Point(3 3)@2001-01-01 08:20:00)}');

    -- Valor en una marca de tiempo
    SELECT CarId, ST_AsText(valueAtTimestamp(Trip, timestamptz '2001-01-01 08:10:00'))
    FROM Trips;
    -- 10 | POINT(2 0)
    -- 20 | POINT(1 1)

    -- Restricción a un valor
    SELECT CarId, asText(atValues(Trip, geometry 'Point(2 0)'))
    FROM Trips;
    -- 10 | {"[POINT(2 0)@2001-01-01 08:10:00+00]"}
    -- 20 |

    -- Restricción a un período
    SELECT CarId, asText(atTime(Trip, tstzspan '[2001-01-01 08:05:00,2001-01-01 08:10:00]'))
    FROM Trips;
    -- 10 | {[POINT(1 0)@2001-01-01 08:05:00+00, POINT(2 0)@2001-01-01 08:10:00+00]}
    -- 20 | {[POINT(0 0)@2001-01-01 08:05:00+00, POINT(1 1)@2001-01-01 08:10:00+00]}

    -- Distancia temporal
    SELECT T1.CarId, T2.CarId, T1.Trip <-> T2.Trip
    FROM Trips T1, Trips T2
    WHERE T1.CarId < T2.CarId;
    /* 10 | 20 | {[1@2001-01-01 08:05:00+00, 1.4142135623731@2001-01-01 08:10:00+00,
       1@2001-01-01 08:15:00+00)} */

## Validez de los tipos temporales

Los valores de los tipos temporales deben satisfacer varias restricciones para que estén bien definidos. Estas restricciones se dan a continuación.

- Las restricciones en el tipo base y el tipo `timestamptz` deben satisfacerse.

- Un valor de secuencia debe estar compuesto por al menos un valor de instante.

- Un valor de secuencia instantánea o con interpolación discreta debe tener límites inferior y superior inclusivos.

- En un valor de secuencia, las marcas de tiempo de los instantes que la componen deben ser diferentes y estar ordenadas.

- En un valor de secuencia con interpolación escalonada, los dos últimos valores deben ser iguales si el límite superior es exclusivo.

- Un valor de conjunto de secuencias debe estar compuesto por al menos un valor de secuencia.

- En un valor de conjunto de secuencias, los valores de las secuencias componentes no deben superponerse y deben estar ordenados.

Se genera un error cuando no se satisface una de estas restricciones. Ejemplos de valores temporales incorrectos son los siguientes.

    -- Valor del tipo de base incorrecto
    SELECT tbool '1.5@2001-01-01 08:00:00';
    -- Valor del tipo base no es un punto
    SELECT tgeompoint 'Linestring(0 0,1 1)@2001-01-01 08:05:00';
    -- Marca de tiempo incorrecta
    SELECT tint '2@2001-02-31 08:00:00';
    -- Secuencia vacía
    SELECT tint '';
    -- Límites incorrectos para la secuencia instantánea
    SELECT tint '[1@2001-01-01 09:00:00)';
    -- Marcas de tiempo duplicadas
    SELECT tint '[1@2001-01-01 08:00:00, 2@2001-01-01 08:00:00]';
    -- Marcas de tiempo desordenadas
    SELECT tint '[1@2001-01-01 08:10:00, 2@2001-01-01 08:00:00]';
    -- Valor final incorrecto para interpolación escalonada
    SELECT tint '[1@2001-01-01 08:00:00, 2@2001-01-01 08:10:00)';
    -- Conjunto de secuencias vacío
    SELECT tint '{[]}';
    -- Marcas de tiempo duplicadas
    SELECT tint '{1@2001-01-01 08:00:00, 2@2001-01-01 08:00:00}';
    -- Períodos superpuestos
    SELECT tint '{[1@2001-01-01 08:00:00, 1@2001-01-01 10:00:00),
      [2@2001-01-01 09:00:00, 2@2001-01-01 11:00:00)}';

## Temporalización de operaciones

Una forma común de generalizar las operaciones tradicionales a los tipos temporales es aplicar la operación en cada instante, lo que da un valor temporal como resultado. En ese caso, la operación sólo se define en la intersección de las extensiones temporales de los operandos; si las extensiones temporales son disjuntas, el resultado es nulo. Por ejemplo, los operadores de comparación temporal, como `#<`, determinan si los valores tomados por sus operandos en cada instante satisfacen la condición y devuelven un booleano temporal. A continuación se dan ejemplos de las diversas generalizaciones de los operadores.

    -- Comparación temporal
    SELECT tfloat '[2@2001-01-01, 2@2001-01-03)' #< tfloat '[1@2001-01-01, 3@2001-01-03)';
    -- {[f@2001-01-01, f@2001-01-02], (t@2001-01-02, t@2001-01-03)}
    SELECT tfloat '[1@2001-01-01, 3@2001-01-03)' #< tfloat '[3@2001-01-03, 1@2001-01-05)';
    -- NULL

    -- Adición temporal
    SELECT tint '[1@2001-01-01, 1@2001-01-03)' + tint '[2@2001-01-02, 2@2001-01-05)';
    -- [3@2001-01-02, 3@2001-01-03)

    -- Intersección temporal
    SELECT tintersects(tgeompoint '[Point(0 1)@2001-01-01, Point(3 1)@2001-01-04)',
    geometry 'Polygon((1 0,1 2,2 2,2 0,1 0))');
    -- {[f@2001-01-01, t@2001-01-02, t@2001-01-03], (f@2001-01-03, f@2001-01-04]}

    -- Distancia temporal
    SELECT tgeompoint '[Point(0 0)@2001-01-01 08:00:00, Point(0 1)@2001-01-03 08:10:00)' <->
    tgeompoint '[Point(0 0)@2001-01-02 08:05:00, Point(1 1)@2001-01-05 08:15:00)';
    -- [0.5@2001-01-02 08:05:00+00, 0.745184033794557@2001-01-03 08:10:00+00)

Otro requisito común es determinar si los operandos satisfacen alguna vez o siempre una condición con respecto a una operación. Estos se pueden obtener aplicando los operadores de comparación alguna vez o siempre. Estos operadores se indican anteponiendo los operadores de comparación tradicionales con, respectivamente, `?` (alguna vez) y `%` (siempre). A continuación se dan ejemplos de operadores de comparación alguna vez y siempre.

    -- ¿Se cruzan los operandos alguna vez?
    SELECT eIntersects(tgeompoint '[Point(0 1)@2001-01-01, Point(3 1)@2001-01-04)',
      geometry 'Polygon((1 0,1 2,2 2,2 0,1 0))') ?= true;
    -- true

    -- ¿Se cruzan los operandos siempre?
    SELECT aIntersects(tgeompoint '[Point(0 1)@2001-01-01, Point(3 1)@2001-01-04)',
      geometry 'Polygon((0 0,0 2,4 2,4 0,0 0))') %= true;
    -- true

    -- ¿Es el operando izquierdo alguna vez menor que el derecho?
    SELECT (tfloat '[1@2001-01-01, 3@2001-01-03)' ?<
      tfloat '[3@2001-01-01, 1@2001-01-03)') ?= true;
    -- true

    -- ¿Es el operando izquierdo siempre menor que el derecho?
    SELECT (tfloat '[1@2001-01-01, 3@2001-01-03)' %<
      tfloat '[2@2001-01-01, 4@2001-01-03)') %= true;
    -- true

Por ejemplo, la función `eIntersects` determina si hay un instante en el que los dos argumentos se cruzan espacialmente.

A continuación describimos las funciones y operadores para tipos temporales. Para mayor concisión, en los ejemplos usamos principalmente secuencias compuestas por dos instantes.

## Notación

A continuación presentamos las funciones y operadores para tipos temporales. Estas funciones y operadores son polimórficos, es decir, sus argumentos pueden ser de varios tipos y el tipo del resultado puede depender del tipo de los argumentos. Para expresar esto, usamos la siguiente notación:

- `time` representa cualquier tipo de tiempo, es decir, `timestamptz`, `tstzspan`, `tstzset` o `tstzspanset`,

- `ttype` representa cualquier tipo temporal,

- `ttypeInst`, `ttypSeq` y `ttypeSeqSet` representan cualquier tipo temporal con subtipo instante, secuencia y conjunto de secuencias

- `tdisc` representa cualquier tipo temporal con tipo de base discreto, es decir, `tbool`, `tint`, or `ttext`,

- `tcont` cualquier tipo temporal con tipo de base contínuo, es decir, `tfloat`, `tgeompoint`, or `tgeogpoint`,

- `ttypeDiscSeq` y `ttypeContSeq` representan cualquier tipo temporal con subtipo secuencia y, respectivamente, interpolación discreta y contínua,

- `base` representa cualquier tipo de base de un tipo temporal, es decir, `boolean`, `integer`, `float`, `text`, `geometry` o `geography`,

- `values` representa cualquier conjunto de valores de un tipo base de un tipo temporal, por ejemplo, `integer`, `intset`, `intspan` y `intspanset` para el tipo base `integer`

- `type[]` representa una matriz de `type`.

- `<type>` en el nombre de una función representa las funciones obtenidas al remplazar `<type>` por un `type` específico. Por ejemplo, `tintDiscSeq` o `tfloatDiscSeq` son representadas por `ttypeDiscSeq`.

## Entrada y salida

MobilityDB generaliza los formatos de entrada y salida Well-Known Text (WKT), Moving Features JSON (MF-JSON) y Well-Known Binary (WKB) del Open Geospatial Consortium para todos los tipos temporales. Presentamos a continuación las funciones de entrada y salida para los tipos temporales. Empezamos describiendo formato WKT.

Un valor de instante es un par de la forma `v@t`, donde `v` es un valor del tipo de base y `t` es un valor de `timestamptz`. Ejemplos de entrada de valores de instante son los siguientes:

    SELECT tbool 'true@2001-01-01 08:00:00';
    SELECT tint '1@2001-01-01 08:00:00';
    SELECT tfloat '1.5@2001-01-01 08:00:00';
    SELECT ttext 'AAA@2001-01-01 08:00:00';
    SELECT tgeompoint 'Point(0 0)@2017-01-01 08:00:05';
    SELECT tgeogpoint 'Point(0 0)@2017-01-01 08:00:05';
    SELECT tgeometry 'Linestring(0 0,1 1)@2017-01-01 08:00:05';
    SELECT tgeography 'Polygon((0 0,1 1,2 0,0 0))@2017-01-01 08:00:05';

Un valor de secuencia es un conjunto de valores `v1@t1,...,vn@tn` delimitado por límites superior e inferior, que pueden ser inclusivo (representados por ‘`[`’ y ‘`]`’) o exclusivos (representados por ‘`(`’ y ‘`)`’). Un valor de secuencia compuesto por una sola pareja `v@t` se denomina secuencia instantánea. Los valores de secuencia tienen una función de interpolación asociada que puede ser discreta, lineal o escalonada. Por definición, los límites inferior y superior de una secuencia instantánea o de un valor de secuencia con interpolación discreta son inclusivos. La extensión temporal de un valor de secuencia con interpolación discreta es un conjunto de marcas de tiempo. Ejemplos de valores de secuencia con interpolación discreta son los siguientes.

    SELECT tbool '{true@2001-01-01 08:00:00, false@2001-01-03 08:00:00}';
    SELECT tint '{1@2001-01-01 08:00:00, 2@2001-01-03 08:00:00}';
    SELECT tint '{1@2001-01-01 08:00:00}'; -- Instantaneous sequence
    SELECT tfloat '{1.0@2001-01-01 08:00:00, 2.0@2001-01-03 08:00:00}';
    SELECT ttext '{AAA@2001-01-01 08:00:00, BBB@2001-01-03 08:00:00}';
    SELECT tgeompoint '{Point(0 0)@2017-01-01 08:00:00, Point(0 1)@2017-01-02 08:05:00}';
    SELECT tgeogpoint '{Point(0 0)@2017-01-01 08:00:00, Point(0 1)@2017-01-02 08:05:00}';
    SELECT tgeometry '{Point(0 0)@2017-01-01 08:00:00,
      Linestring(0 0,0 1)@2017-01-02 08:05:00}';
    SELECT tgeography '{Point(0 0)@2017-01-01 08:00:00,
      Polygon((0 0,1 1,2 0,0 0))@2017-01-02 08:05:00}';

La extensión temporal de un valor de secuencia con interpolación lineal o escalonada es un período definido por el primer y el últimpo instante, así como por los límites inferior y superior. Ejemplos de valores de secuencia con interpolación lineal son los siguientes:

    SELECT tbool '[true@2001-01-01 08:00:00, true@2001-01-03 08:00:00]';
    SELECT tint '[1@2001-01-01 08:00:00, 1@2001-01-03 08:00:00]';
    SELECT tfloat '[2.5@2001-01-01 08:00:00, 3@2001-01-03 08:00:00, 1@2001-01-04 08:00:00]';
    SELECT tfloat '[1.5@2001-01-01 08:00:00]'; -- Instantaneous sequence
    SELECT ttext '[BBB@2001-01-01 08:00:00, BBB@2001-01-03 08:00:00]';
    SELECT tgeompoint '[Point(0 0)@2017-01-01 08:00:00, Point(0 0)@2017-01-01 08:05:00)';
    SELECT tgeogpoint '[Point(0 0)@2017-01-01 08:00:00, Point(0 1)@2017-01-01 08:05:00,
      Point(0 0)@2017-01-01 08:10:00)';
    SELECT tgeometry '[Point(0 0)@2017-01-01 08:00:00,
      Linestring(0 0,0 1)@2017-01-02 08:05:00]';
    SELECT tgeography '[Point(0 0)@2017-01-01 08:00:00,
      Polygon((0 0,1 1,2 0,0 0))@2017-01-02 08:05:00]';

Los valores de secuencia cuyo tipo base es continuo pueden especificar que la interpolación es escalonada con el prefijo `Interp=Step`. Si no se especifica, se supone que la interpolación es lineal por defecto. A continuación se dan ejemplos de valores de secuencia con interpolación escalonada:

    SELECT tfloat 'Interp=Step;[2.5@2001-01-01 08:00:00, 3@2001-01-01 08:10:00]';
    SELECT tgeompoint 'Interp=Step;[Point(0 0)@2017-01-01 08:00:00,
      Point(1 1)@2017-01-01 08:05:00, Point(1 1)@2017-01-01 08:10:00)';
    SELECT tgeompoint 'Interp=Step;[Point(0 0)@2017-01-01 08:00:00,
     Point(1 1)@2017-01-01 08:05:00, Point(0 0)@2017-01-01 08:10:00)';
    ERROR:  Invalid end value for temporal sequence with step interpolation
    SELECT tgeogpoint 'Interp=Step;[Point(0 0)@2017-01-01 08:00:00,
      Point(1 1)@2017-01-01 08:10:00]';

Los dos últimos instantes de un valor de secuencia con interpolación discreta y límite superior exclusivo deben tener el mismo valor base, como se muestra en el segundo y tercer ejemplo anteriores.

Un valor de conjunto de secuencias es un conjunto `{v1,...,vn}` donde cada `vi` es un valor de secuencia. La interpolación de los valores conjunto de secuencias solo puede ser lineal o escalonada, no discreta. Todas las secuencias que componen un valor de conjunto de secuencias deben tener la misma interpolación. La extensión temporal de un valor de conjunto de secuencias es un conjunto de períodos. Ejemplos de valores de conjunto de secuencias con interpolación lineal son los siguientes:

    SELECT tbool '{[false@2001-01-01 08:00:00, false@2001-01-03 08:00:00),
      [true@2001-01-03 08:00:00], (false@2001-01-04 08:00:00, false@2001-01-06 08:00:00]}';
    SELECT tint '{[1@2001-01-01 08:00:00, 1@2001-01-03 08:00:00),
      [2@2001-01-04 08:00:00, 3@2001-01-05 08:00:00, 3@2001-01-06 08:00:00]}';
    SELECT tfloat '{[1@2001-01-01 08:00:00, 2@2001-01-03 08:00:00, 2@2001-01-04 08:00:00,
      3@2001-01-06 08:00:00]}';
    SELECT ttext '{[AAA@2001-01-01 08:00:00, BBB@2001-01-03 08:00:00, BBB@2001-01-04 08:00:00),
      [CCC@2001-01-05 08:00:00, CCC@2001-01-06 08:00:00]}';
    SELECT tgeompoint '{[Point(0 0)@2017-01-01 08:00:00, Point(0 1)@2017-01-01 08:05:00),
      [Point(0 1)@2017-01-01 08:10:00, Point(1 1)@2017-01-01 08:15:00)}';
    SELECT tgeogpoint '{[Point(0 0)@2017-01-01 08:00:00, Point(0 1)@2017-01-01 08:05:00),
      [Point(0 1)@2017-01-01 08:10:00, Point(1 1)@2017-01-01 08:15:00)}';
    SELECT tgeometry
      '{[Point(0 0)@2017-01-01 08:00:00, Linestring(0 0,1 1)@2017-01-01 08:05:00),
        [Point(0 1)@2017-01-01 08:10:00, Point(1 1)@2017-01-01 08:15:00)}';
    SELECT tgeography
      '{[Point(0 0)@2017-01-01 08:00:00, Polygon((0 0,1 1,2 0,0 0))@2017-01-01 08:05:00),
        [Point(0 1)@2017-01-01 08:10:00, Linestring(0 0,1 1)@2017-01-01 08:15:00)}';

Los valores de conjunto de secuencias cuyo tipo base es continuo pueden especificar que la interpolación es escalonada con el prefijo `Interp=Step`. Si no se especifica, se supone que la interpolación es lineal por defecto. A continuación se dan ejemplos de valores de conjunto de secuencias con interpolación escalonada:

    SELECT tfloat 'Interp=Step;{[1@2001-01-01 08:00:00, 2@2001-01-03 08:00:00,
      2@2001-01-04 08:00:00, 3@2001-01-06 08:00:00]}';
    SELECT tgeompoint 'Interp=Step;{[Point(0 0)@2017-01-01 08:00:00,
      Point(0 1)@2017-01-01 08:05:00], [Point(0 1)@2017-01-01 08:10:00,
      Point(0 1)@2017-01-01 08:15:00)}';
    SELECT tgeogpoint 'Interp=Step;{[Point(0 0)@2017-01-01 08:00:00,
      Point(0 1)@2017-01-01 08:05:00], [Point(0 1)@2017-01-01 08:10:00,
      Point(0 1)@2017-01-01 08:15:00)}';

Para geometrías temporales, es posible especificar el identificador de referencia espacial (SRID) utilizando la representación extendida de texto conocido (EWKT) de la siguiente manera:

    SELECT tgeompoint 'SRID=5435;[Point(0 0)@2001-01-01,Point(0 1)@2001-01-02]'
    SELECT tgeography 'SRID=7844;[Point(0 0)@2001-01-01,Linestring(1 0,0 1)@2001-01-02]'

Todas las geometrías componentes serán entonces del SRID dado. Además, cada geometría componente puede especificar su SRID con el formato EWKT como en el siguiente ejemplo

    SELECT tgeompoint '[SRID=5435;Point(0 0)@2001-01-01,SRID=5435;Point(0 1)@2001-01-02]'

Se genera un error si las geometrías componentes no están todas en el mismo SRID o si el SRID de una geometría componente es diferente al del punto temporal.

    SELECT tgeompoint '[SRID=5435;Point(0 0)@2001-01-01,SRID=4326;Point(0 1)@2001-01-02]';
    -- ERROR: Geometry SRID (4326) does not match temporal type SRID (5435)
    SELECT tgeography 'SRID=7844;[SRID=4326;Point(0 0)@2001-01-01,
      SRID=4326;Linestring(1 0,0 1)@2001-01-02]';
    -- ERROR: Geometry SRID (4326) does not match temporal type SRID (7844)

Si no se especifica, el SRID predeterminado para los geometrías temporales es 0 (desconocido) y para los geografías temporales es 4326 (WGS 84). Los puntos temporales con interpolación escalonada también pueden especificar el SRID, como se muestra a continuación.

    SELECT tgeompoint 'SRID=5435,Interp=Step;[Point(0 0)@2001-01-01,
      Point(0 1)@2001-01-02]';
    SELECT tgeogpoint 'Interp=Step;[SRID=4326;Point(0 0)@2001-01-01,
      SRID=4326;Point(0 1)@2001-01-02]';

Damos a continuación las funciones de entrada y salida en formato textual (Well-Known Text o WKT), binario (Well-Known Binary o WKB) y Moving Features JSON (MF-JSON) para los tipos alfanuméricos temporales. Las funciones correspondientes para los puntos temporales se detallan en la tgeo_inout. El formato de salida predeterminado de todos los tipos alfanuméricos temporales es el formato de texto conocido. La función `asText` que se da a continuación permite determinar la salida de valores temporales de punto flotante.

- Devuelve la representación textual conocida (Well-Known Text o WKT)

  `asText(tfloat,maxdecdigits=15) → text`

  El argumento `maxdecdigits` puede usarse para establecer el número máximo de decimales en la salida de los valores en punto flotante (por defecto 15).

      SELECT asText(tfloat '[10.55@2001-01-01, 25.55@2001-01-02]', 0);
      -- [11@2001-01-01, 26@2001-01-02]
      SELECT asText(tgeometry
        '[Point(1.55 1.55)@2001-01-01,Linestring(1.55 1.55,3.55 3.55)@2001-01-02]', 0);
      -- [Point(1 1)@2001-01-01, Linestring(1 1,3 3)@2001-01-02]

- Devuelve la representación JSON de características móviles (Moving Features JSON o MF-JSON)

  `asMFJSON(ttype,options=0,flags=0,maxdecdigits=15) → bytea`

  El argumento `options` puede usarse para agregar un cuadro delimitador en la salida MFJSON:

  - 0: significa que no hay opción (valor por defecto)

  - 1: cuadro delimitador MFJSON

  El argumento `flags` puede usarse para personalizar la salida JSON, por ejemplo, para producir una salida JSON fácil de leer (para lectores humanos). Consulte la documentación de la biblioteca `json-c` para conocer los valores possible. Los valores típicos son los siguientes:

  - 0: means no option (default value)

  - 1: JSON_C_TO_STRING_SPACED

  - 2: JSON_C_TO_STRING_PRETTY

  El argumento `maxdecdigits` puede usarse para establecer el número máximo de decimales en la salida de los valores en punto flotante (por defecto 15).

      SELECT asMFJSON(tbool 't@2001-01-01 18:00:00', 1);
      /* {"type":"MovingBoolean","period":{"begin":"2001-01-01T18:00:00+01",
        "end":"2001-01-01T18:00:00+01","lowerInc":true,"upperInc":true},
        "values":[true],"datetimes":["2001-01-01T18:00:00+01"],"interpolation":"None"} */
      SELECT asMFJSON(tint '{10@2001-01-01 18:00:00, 25@2001-01-01 18:10:00}', 1);
      /* {"type":"MovingInteger","bbox":[10,25],"period":{"begin":"2001-01-01T18:00:00+01",
         "end":"2001-01-01T18:10:00+01"},"values":[10,25],"datetimes":["2001-01-01T18:00:00+01",
         "2001-01-01T18:10:00+01"],"lowerInc":true,"upperInc":true,
         "interpolation":"Discrete"} */
      SELECT asMFJSON(tfloat '[10.5@2001-01-01 18:00:00+02, 25.5@2001-01-01 18:10:00+02]');
      /* {"type":"MovingFloat","values":[10.5,25.5],"datetimes":["2001-01-01T17:00:00+01",
        "2001-01-01T17:10:00+01"],"lowerInc":true,"upperInc":true,"interpolation":"Linear"} */
      SELECT asMFJSON(ttext '{[walking@2001-01-01 18:00:00+02,
        driving@2001-01-01 18:10:00+02]}');
      /* {"type":"MovingText","sequences":[{"values":["walking","driving"],
        "datetimes":["2001-01-01T17:00:00+01","2001-01-01T17:10:00+01"],
        "lowerInc":true,"upperInc":true}],"interpolation":"Step"} */
      SELECT asMFJSON(tgeometry '{[Point(1 1)@2001-01-01 18:00:00+02,
        Linestring(1 1,2 2)@2001-01-01 18:10:00+02]}');
      /* {"type":"MovingGeometry","sequences":[{"values":[{"type":"Point",
          "coordinates":[1,1]},{"type":"LineString","coordinates":[[1,1],[2,2]]}],
          "datetimes":["2001-01-01T17:00:00+01","2001-01-01T17:10:00+01"],
          "lower_inc":true,"upper_inc":true}],"interpolation":"Step"} */

- Devuelve la representación binaria conocida (Well-Known Binary o WKB) o la representación hexadecimal binaria conocida (HexWKB)

  `asBinary(ttype,endian text='') → bytea`

  `asHexWKB(ttype,endian text='') → text`

  El resultado se codifica utilizando la codificación little-endian (NDR) o big-endian (XDR). Si no se especifica ninguna codificación, se utiliza la codificación de la máquina.

      SELECT asBinary(tbool 'true@2001-01-01');
      -- \x011a000101009c57d3c11c0000
      SELECT asBinary(tfloat '1.5@2001-01-01');
      -- \x01210001000000000000f83f009c57d3c11c0000
      SELECT asHexWKB(tint '1@2001-01-01', 'XDR');
      -- 000023010000000100001CC1D3579C00
      SELECT asHexWKB(ttext 'AAA@2001-01-01');
      -- 01290001040000000000000041414100009C57D3C11C0000

- Entrar a partir de la representación Moving Features JSON (MF-JSON)

  `ttypeFromMFJSON(bytea) → ttype`

  Hay una función por tipo temporal, el nombre de esta función tiene como prefijo el nombre del tipo, que son `tbool` o `tint` en los ejemplos a continuación

      SELECT tboolFromMFJSON(text
        '{"type":"MovingBoolean","period":{"begin":"2001-01-01T18:00:00+01",
        "end":"2001-01-01T18:00:00+01","lowerInc":true,"upperInc":true},
        "values":[true],"datetimes":["2001-01-01T18:00:00+01"],"interpolation":"None"}');
      -- t@2001-01-01 18:00:00
      SELECT tintFromMFJSON(text
        '{"type":"MovingInteger","bbox":[10,25],"period":{"begin":"2001-01-01T18:00:00+01",
         "end":"2001-01-01T18:10:00+01"},"values":[10,25],"datetimes":["2001-01-01T18:00:00+01",
         "2001-01-01T18:10:00+01"],"lowerInc":true,"upperInc":true,
         "interpolation":"Discrete"}');
      -- {10@2001-01-01 18:00:00, 25@2001-01-01 18:10:00}
      SELECT tfloatFromMFJSON(text
        '{"type":"MovingFloat","values":[10.5,25.5],"datetimes":["2001-01-01T17:00:00+01",
         "2001-01-01T17:10:00+01"],"lowerInc":true,"upperInc":true,
         "interpolation":"Linear"}');
      -- [10.5@2001-01-01 18:00:00, 25.5@2001-01-01 18:10:00]'
      SELECT ttextFromMFJSON(text
        '{"type":"MovingText","sequences":[{"values":["walking","driving"],
        "datetimes":["2001-01-01T17:00:00+01","2001-01-01T17:10:00+01"],
        "lowerInc":true,"upperInc":true}],"interpolation":"Step"}');
      -- {["walking"@2001-01-01 18:00:00, "driving"@2001-01-01 18:10:00]}');
      SELECT asText(tgeometryFromMFJSON(text
        '{"type":"MovingGeometry","sequences":[{"values":[{"type":"Point",
        "coordinates":[1,1]},{"type":"LineString","coordinates":[[1,1],[2,2]]}],
        "datetimes":["2001-01-01T17:00:00+01","2001-01-01T17:10:00+01"],
        "lower_inc":true,"upper_inc":true}],"interpolation":"Step"}'));
      -- {[POINT(1 1)@2001-01-01 17:00:00, LINESTRING(1 1,2 2)@2001-01-01 17:10:00]}

- Entrar a partir de la representación binaria conocida (WKB) o de la representación hexadecimal binaria conocida (HexWKB)

  `ttypeFromBinary(bytea) → ttype`

  `ttypeFromHexWKB(text) → ttype`

  Hay una función por tipo temporal, el nombre de la función tiene como prefijo el nombre del tipo, que son `tbool` o `tint` en los ejemplos a continuación.

      SELECT tboolFromBinary('\x011a000101009c57d3c11c0000');
      -- t@2001-01-01
      SELECT tintFromBinary('\x000023010000000100001cc1d3579c00');
      -- 1@2001-01-01
      SELECT tfloatFromBinary('\x01210001000000000000f83f009c57d3c11c0000');
      -- 1.5@2001-01-01
      SELECT ttextFromBinary('\x01290001040000000000000041414100009c57d3c11c0000');
      -- "AAA"@2001-01-01
      SELECT tboolFromHexWKB('011A000101009C57D3C11C0000');
      -- t@2001-01-01
      SELECT tintFromHexWKB('000023010000000100001CC1D3579C00');
      -- 1@2001-01-01
      SELECT tfloatFromHexWKB('01210001000000000000F83F009C57D3C11C0000');
      -- 1.5@2001-01-01
      SELECT ttextFromHexWKB('01290001040000000000000041414100009C57D3C11C0000');
      -- "AAA"@2001-01-01

## Constructores

A continuación, damos las funciones de constructor para los distintos subtipos. El uso de la función de constructor suele ser más conveniente que escribir una constante literal.

- Constructores para tipos temporales que tienen un valor constante

  Estos constructores tienen dos argumentos, un tipo base y un tipo de tiempo, donde el último es un valor de `timestamptz`, `tstzset`, `tstzspan` o `tstzspanset` para construir, respectivamente, un valor de subtipo instante, una secuencia con interpolación discreta, una secuencia con interpolación linear o escalonada o un conjunto de secuencias. Las funciones para valores de secuencia o de conjunto de secuencias con tipo de base continuo tienen además un tercer argumento opcional que indica si el valor temporal resultante tiene interpolación lineal o escalonada. Se asume por defecto una interpolación lineal si el argumento no se especifica.

  `ttype(base,timestamptz) → ttypeInst`

  `ttype(base,tstzset) → ttypeDiscSeq`

  `ttype(base,tstzspan,interp='linear') → ttypeContSeq`

  `ttype(base,tstzspanset,interp='linear') → ttypeSeqSet`

      SELECT tbool(true, timestamptz '2001-01-01');
      SELECT tint(1, timestamptz '2001-01-01');
      SELECT tfloat(1.5, tstzset '{2001-01-01, 2001-01-02}');
      SELECT ttext('AAA', tstzset '{2001-01-01, 2001-01-02}');
      SELECT tfloat(1.5, tstzspan '[2001-01-01, 2001-01-02]');
      SELECT tfloat(1.5, tstzspan '[2001-01-01, 2001-01-02]', 'step');
      SELECT tgeompoint('Point(0 0)', tstzspan '[2001-01-01, 2001-01-02]');
      SELECT tgeography('SRID=7844;Point(0 0)', tstzspanset '{[2001-01-01, 2001-01-02],
        [2001-01-03, 2001-01-04]}', 'step');

- Constructores para tipos temporales de subtipo secuencia

  Estos constructores tienen un primer argumento obligatorio, que es una matriz de valores de los valores instantáneos correspondientes y argumentos opcionales adicionales. El segundo argumento establece la interpolación. Si no se proporciona el argumento, es por defecto escalonada para los tipos de base base discretos como los enteros y es lineal para tipos de base continuous como los flotantes. Se genera un error cuando se establece la interpolación lineal para valores temporales con tipos de base discretos. Para secuencias continuas, el tercero y el cuarto argumentos son valores booleanos que indican, respectivamente, si los límites izquierdo y derecho son inclusivos o exclusivos. Se supone que estos argumentos son verdaderos de forma predeterminada si no se especifican.

  `ttypeSeq(ttypeInst[],interp={'step','linear'},leftInc bool=true,`

  `rightInc bool=true) → ttypeSeq`

      SELECT tboolSeq(ARRAY[tbool 'true@2001-01-01 08:00:00','false@2001-01-01 08:05:00'],
        'discrete');
      SELECT tintSeq(ARRAY[tint '1@2001-01-01 08:00:00', '2@2001-01-01 08:05:00']);
      SELECT tintSeq(ARRAY[tint '1@2001-01-01 08:00:00', '2@2001-01-01 08:05:00'], 'linear');
      -- ERROR:  The temporal type cannot have linear interpolation
      SELECT tfloatSeq(ARRAY[tfloat '1.0@2001-01-01 08:00:00', '2.0@2001-01-01 08:05:00'],
        'step', false, true);
      SELECT ttextSeq(ARRAY[ttext 'AAA@2001-01-01 08:00:00', 'BBB@2001-01-01 08:05:00']);
      SELECT tgeompointSeq(ARRAY[tgeompoint 'Point(0 0)@2001-01-01 08:00:00',
        'Point(0 1)@2001-01-01 08:05:00', 'Point(1 1)@2001-01-01 08:10:00'], 'discrete');
      SELECT tgeographySeq(ARRAY[tgeography 'Point(1 1)@2001-01-01 08:00:00',
        'Point(2 2)@2001-01-01 08:05:00']);

- Constructores para tipos temporales de subtipo conjunto de secuencias

  `ttypeSeqSet(ttypeContSeq[]) → ttypeSeqSet`

  `ttypeSeqSetGaps(ttypeInst[],maxt=NULL,maxdist=NULL,interp='linear') → ttypeSeqSet`

  Un primer conjunto de constructores tiene un solo argumento, que es una matriz de valores de los valores de secuencia correspondientes. La interpolación del valor temporal resultante depende de la interpolación de las secuencias que lo componen. Se genera un error si las secuencias que componen la matriz tienen una interpolación diferente.

      SELECT tboolSeqSet(ARRAY[tbool '[false@2001-01-01 08:00:00, false@2001-01-01 08:05:00)',
        '[true@2001-01-01 08:05:00]','(false@2001-01-01 08:05:00, false@2001-01-01 08:10:00)']);
      SELECT tintSeqSet(ARRAY[tint '[1@2001-01-01 08:00:00, 2@2001-01-01 08:05:00,
        2@2001-01-01 08:10:00, 2@2001-01-01 08:15:00)']);
      SELECT tfloatSeqSet(ARRAY[tfloat '[1.0@2001-01-01 08:00:00, 2.0@2001-01-01 08:05:00,
        2.0@2001-01-01 08:10:00]', '[2.0@2001-01-01 08:15:00, 3.0@2001-01-01 08:20:00)']);
      SELECT tfloatSeqSet(ARRAY[tfloat 'Interp=Step;[1.0@2001-01-01 08:00:00,
        2.0@2001-01-01 08:05:00, 2.0@2001-01-01 08:10:00]',
        'Interp=Step;[3.0@2001-01-01 08:15:00, 3.0@2001-01-01 08:20:00)']);
      SELECT ttextSeqSet(ARRAY[ttext '[AAA@2001-01-01 08:00:00, AAA@2001-01-01 08:05:00)',
        '[BBB@2001-01-01 08:10:00, BBB@2001-01-01 08:15:00)']);
      SELECT tgeompointSeqSet(ARRAY[tgeompoint '[Point(0 0)@2001-01-01 08:00:00,
        Point(0 1)@2001-01-01 08:05:00, Point(0 1)@2001-01-01 08:10:00)',
        '[Point(0 1)@2001-01-01 08:15:00, Point(0 0)@2001-01-01 08:20:00)']);
      SELECT tgeographySeqSet(ARRAY[tgeography
        '[Point(0 0)@2001-01-01 08:00:00, Point(0 0)@2001-01-01 08:05:00)',
        '[Point(1 1)@2001-01-01 08:10:00, Point(1 1)@2001-01-01 08:15:00)']);
      SELECT tfloatSeqSet(ARRAY[tfloat 'Interp=Step;[1.0@2001-01-01 08:00:00,
        2.0@2001-01-01 08:05:00, 2.0@2001-01-01 08:10:00]',
        '[3.0@2001-01-01 08:15:00, 3.0@2001-01-01 08:20:00)']);
      -- ERROR:  The temporal values must have the same interpolation

  Otro conjunto de constructores para valores de conjunto de secuencias tiene como primer argumento una matriz de valores de instante correspondientes, y dos argumentos que establecen un intervalo de tiempo máximo y una distancia máxima tal que se introduce un espacio entre secuencias del resultado siempre que dos instantes de entrada consecutivos tengan un intervalo de tiempo o una distancia mayor que estos valores. Para puntos temporales, la distancia se especifica en unidades del sistema de coordenadas. Estos dos argumentos de brechas son opcionales, pero al menos uno de ellos debe especificarse. Además, cuando el tipo base es continuo, un último argumento adicional establece si la interpolación es escalonada o lineal. Si no se especifica este argumento, se asume que es lineal por defecto.

  Los parámetros de la función dependen del tipo temporal. Por ejemplo, el parámetro de interpolación no está permitido para tipos temporales con subtipos discretos como `tint`. De manera similar, el parámetro `maxdist` no está permitido para tipos escalares como `ttext` que no tienen una función de distancia estándar.

      SELECT tintSeqSetGaps(ARRAY[tint '1@2001-01-01', '3@2001-01-02', '4@2001-01-03',
        '5@2001-01-05']);
      -- {[1@2001-01-01, 3@2001-01-02, 4@2001-01-03, 5@2001-01-05]}
      SELECT tintSeqSetGaps(ARRAY[tint '1@2001-01-01', '3@2001-01-02', '4@2001-01-03',
        '5@2001-01-05'], '1 day', 1);
      -- {[1@2001-01-01], [3@2001-01-02, 4@2001-01-03], [5@2001-01-05]}
      SELECT ttextSeqSetGaps(ARRAY[ttext 'AA@2001-01-01', 'BB@2001-01-02', 'AA@2001-01-03',
        'CC@2001-01-05'], '1 day');
      -- {["AA"@2001-01-01, "BB"@2001-01-02, "AA"@2001-01-03], ["CC"@2001-01-05]}
      SELECT asText(tgeometrySeqSetGaps(ARRAY[tgeometry 'Point(1 1)@2001-01-01',
        'Linestring(2 2,3 3)@2001-01-02', 'Point(4 2)@2001-01-03',
        'Polygon((5 0,6 1,7 0,5 0))@2001-01-05'], '1 day', 1));
      /* {[POINT(1 1)@2001-01-01], [LINESTRING(2 2,3 3)@2001-01-02],
         [POINT(4 2)@2001-01-03], [POLYGON((5 0,6 1,7 0,5 0))@2001-01-05]} */
      SELECT asText(tgeompointSeqSetGaps(ARRAY[tgeompoint 'Point(1 1)@2001-01-01',
        'Point(2 2)@2001-01-02', 'Point(3 2)@2001-01-03', 'Point(3 2)@2001-01-05'],
        '1 day', 1, 'step'));
      /* Interp=Step;{[POINT(1 1)@2001-01-01], [POINT(2 2)@2001-01-02, POINT(3 2)@2001-01-03],
         [POINT(3 2)@2001-01-05]} */

## Conversión de tipos

Un valor temporal se puede convertir en un tipo compatible usando la notación `CAST(ttype1 AS ttype2)` o `ttype1::ttype2`.

- Convertir un valor temporal a un intervalo de marcas de tiempo

  `ttype::tstzspan`

      SELECT tint '[1@2001-01-01, 2@2001-01-03]'::tstzspan;
      -- [2001-01-01, 2001-01-03]
      SELECT ttext '(A@2001-01-01, B@2001-01-03, C@2001-01-05]'::tstzspan;
      -- (2001-01-01, 2001-01-05]
      SELECT tgeompoint '[Point(1 1)@2001-01-01, Point(3 3)@2001-01-03]'::tstzspan;
      -- [2001-01-01, 2001-01-03]

## Accesores

- Devuelve el tamaño de la memoria en bytes

  `memSize(ttype) → integer`

      SELECT memSize(tint '{1@2001-01-01, 2@2001-01-02, 3@2001-01-03}');
      -- 176

- Devuelve el subtipo temporal

  `tempSubtype(ttype) → {'Instant','Sequence','SequenceSet'}`

      SELECT tempSubtype(tint '[1@2001-01-01, 2@2001-01-02, 3@2001-01-03]');
      -- Sequence

- Devuelve la interpolación

  `interp(ttype) → {'None','Discrete','Step','Linear'}`

      SELECT interp(tbool 'true@2001-01-01');
      -- None
      SELECT interp(tfloat '{1@2001-01-01, 2@2001-01-02, 3@2001-01-03}');
      -- Discrete
      SELECT interp(tint '[1@2001-01-01, 2@2001-01-02, 3@2001-01-03]');
      -- Step
      SELECT interp(tfloat '[1@2001-01-01, 2@2001-01-02, 3@2001-01-03]');
      -- Linear
      SELECT interp(tfloat 'Interp=Step;[1@2001-01-01, 2@2001-01-02, 3@2001-01-03]');
      -- Step
      SELECT interp(tgeompoint 'Interp=Step;[Point(1 1)@2001-01-01,
        Point(2 2)@2001-01-02, Point(3 3)@2001-01-03]');
      -- Step
      SELECT interp(tgeometry '[Point(1 1)@2001-01-01,
        Linestring(1 1,2 2)@2001-01-02, Polygon((3 3,4 4,5 3,3 3))@2001-01-03]');
      -- Step

- Devuelve el valor o la marca de tiempo de un instantes

  `getValue(ttypeInst) → base`

  `getTimestamp(ttypeInst) → timestamptz`

      SELECT getValue(tint '1@2001-01-01');
      -- 1
      SELECT getTimestamp(tfloat '1@2001-01-01');
      -- 2001-01-01

- Devuelve los valores o el tiempo en el que se define el valor temporal

  `getValues(talpha) → {bool[],spanset,textset}`

  `getTime(ttype) → tstzspanset`

      SELECT getValues(tbool '[false@2001-01-01, true@2001-01-02, false@2001-01-03]');
      -- {f,t}
      SELECT getValues(tint '[1@2001-01-01, 3@2001-01-02, 1@2001-01-03]');
      -- {[1, 2), [3, 4)}
      SELECT getValues(tint '{[1@2001-01-01, 2@2001-01-02, 1@2001-01-03],
        [4@2001-01-04, 4@2001-01-05]}');
      -- {[1, 3), [4, 5)}
      SELECT getValues(tfloat '{1@2001-01-01, 2@2001-01-02, 1@2001-01-03}');
      -- {[1, 1], [2, 2]}
      SELECT getValues(tfloat 'Interp=Step;{[1@2001-01-01, 2@2001-01-02, 1@2001-01-03],
        [3@2001-01-04, 3@2001-01-05]}');
      -- {[1, 1], [2, 2], [3, 3]}
      SELECT getValues(tfloat '[1@2001-01-01, 2@2001-01-02, 1@2001-01-03]');
      -- {[1, 2]}
      SELECT getValues(tfloat '{[1@2001-01-01, 2@2001-01-02, 1@2001-01-03],
        [3@2001-01-04, 3@2001-01-05]}');
      -- {[1, 2], [3, 3]}

      SELECT getTime(ttext 'walking@2001-01-01');
      -- {[2001-01-01, 2001-01-01]}
      SELECT getTime(tfloat '{1@2001-01-01, 2@2001-01-02, 1@2001-01-03}');
      -- {[2001-01-01, 2001-01-01], [2001-01-02, 2001-01-02], [2001-01-03, 2001-01-03]}
      SELECT getTime(tint '[1@2001-01-01, 1@2001-01-15)');
      -- {[2001-01-01, 2001-01-15)}
      SELECT getTime(tfloat '{[1@2001-01-01, 1@2001-01-10), [12@2001-01-12, 12@2001-01-15]}');
      -- {[2001-01-01, 2001-01-10), [2001-01-12, 2001-01-15]}

- Devuelve el valor inicial, final, o enésimo

  `startValue(ttype) → base`

  `endValue(ttype) → base`

  `valueN(ttype,int) → base`

  La función no tiene en cuenta si los límites son inclusivos o no.

      SELECT startValue(tfloat '(1@2001-01-01, 2@2001-01-03)');
      -- 1
      SELECT endValue(tfloat '{[1@2001-01-01, 2@2001-01-03), [3@2001-01-03, 5@2001-01-05)}');
      -- 5
      SELECT valueN(tfloat '{[1@2001-01-01, 2@2001-01-03), [3@2001-01-03, 5@2001-01-05)}', 3);
      -- 3

- Devuelve el valor en una marca de tiempo

  `valueAtTimestamp(ttype,timestamptz) → base`

      SELECT valueAtTimestamp(tfloat '[1@2001-01-01, 4@2001-01-04)', '2001-01-02');
      -- 2

- Devuelve el intervalo de tiempo

  `duration(ttype,boundspan=false) → interval`

  Se puede poner en verdadero un parámetro adicional para calcular la duración del período limitador, ignorando así los posibles intervalos de tiempo

      SELECT duration(tfloat '{1@2001-01-01, 2@2001-01-03, 2@2001-01-05}');
      -- 00:00:00
      SELECT duration(tfloat '{1@2001-01-01, 2@2001-01-03, 2@2001-01-05}', true);
      -- 4 days
      SELECT duration(tfloat '[1@2001-01-01, 2@2001-01-03, 2@2001-01-05)');
      -- 4 days
      SELECT duration(tfloat '{[1@2001-01-01, 2@2001-01-03), [2@2001-01-04, 2@2001-01-05)}');
      -- 3 days
      SELECT duration(tfloat '{[1@2001-01-01, 2@2001-01-03), [2@2001-01-04, 2@2001-01-05)}',
        true);
      -- 4 days

- ¿Es el instante inicial/final inclusivo?

  `lowerInc(ttype) → bool`

  `upperInc(ttype) → bool`

      SELECT lowerInc(tint '[1@2001-01-01, 2@2001-01-02)');
      -- true
      SELECT upperInc(tfloat '{[1@2001-01-01, 2@2001-01-02), (2@2001-01-02, 3@2001-01-03)}');
      -- false

- Devuelve el número o los instantes diferentes

  `numInstants(ttype) → integer`

  `instants(ttype) → ttypeInst[]`

      SELECT numInstants(tfloat '{[1@2001-01-01, 2@2001-01-02), (2@2001-01-02, 3@2001-01-03)}');
      -- 3
      SELECT instants(tfloat '{[1@2001-01-01, 2@2001-01-02), (2@2001-01-02, 3@2001-01-03)}');
      -- {"1@2001-01-01","2@2001-01-02","3@2001-01-03"}

- Devuelve el instante inicial, final o enésimo

  `startInstant(ttype) → ttypeInst`

  `endInstant(ttype) → ttypeInst`

  `instantN(ttype,integer) → ttypeInst`

  Las funciones no tienen en cuenta si los límites son inclusivos o no.

      SELECT startInstant(tfloat '{[1@2001-01-01, 2@2001-01-02),
        (2@2001-01-02, 3@2001-01-03)}');
      -- 1@2001-01-01
      SELECT endInstant(tfloat '{[1@2001-01-01, 2@2001-01-02), (2@2001-01-02, 3@2001-01-03)}');
      -- 3@2001-01-03
      SELECT instantN(tfloat '{[1@2001-01-01, 2@2001-01-02), (2@2001-01-02, 3@2001-01-03)}', 3);
      -- 3@2001-01-03

- Devuelve el número o las marcas de tiempo diferentes

  `numTimestamps(ttype) → integer`

  `timestamps(ttype) → timestamptz[]`

      SELECT numTimestamps(tfloat '{[1@2001-01-01, 2@2001-01-03),
        [3@2001-01-03, 5@2001-01-05)}');
      -- 3
      SELECT timestamps(tfloat '{[1@2001-01-01, 2@2001-01-03), [3@2001-01-03, 5@2001-01-05)}');
      -- {"2001-01-01", "2001-01-03", "2001-01-05"}

- Devuelve la marca de tiempo inicial, final o enésima

  `startTimestamp(ttype) → timestamptz`

  `endTimestamp(ttype) → timestamptz`

  `timestampN(ttype,integer) → timestamptz`

  Las funciones no tienen en cuenta si los límites son inclusivos o no.

      SELECT startTimestamp(tfloat '[1@2001-01-01, 2@2001-01-03)');
      -- 2001-01-01
      SELECT endTimestamp(tfloat '{[1@2001-01-01, 2@2001-01-03),
        [3@2001-01-03, 5@2001-01-05)}');
      -- 2001-01-05
      SELECT timestampN(tfloat '{[1@2001-01-01, 2@2001-01-03),
        [3@2001-01-03, 5@2001-01-05)}', 3);
      -- 2001-01-05

- Devuelve el número o las secuencias

  `numSequences({ttypeContSeq,ttypeSeqSet}) → integer`

  `sequences({ttypeContSeq,ttypeSeqSet}) → ttypeContSeq[]`

      SELECT numSequences(tfloat '{[1@2001-01-01, 2@2001-01-03),
        [3@2001-01-03, 5@2001-01-05)}');
      -- 2
      SELECT sequences(tfloat '{[1@2001-01-01, 2@2001-01-03), [3@2001-01-03, 5@2001-01-05)}');
      -- {"[1@2001-01-01, 2@2001-01-03)", "[3@2001-01-03, 5@2001-01-05)"}

- Devuelve la secuencia inicial, final, o enésima

  `startSequence({ttypeContSeq,ttypeSeqSet}) → ttypeContSeq`

  `endSequence({ttypeContSeq,ttypeSeqSet}) → ttypeContSeq`

  `sequenceN({ttypeContSeq,ttypeSeqSet},integer) → ttypeContSeq`

      SELECT startSequence(tfloat '{[1@2001-01-01, 2@2001-01-03),
        [3@2001-01-03, 5@2001-01-05)}');
      -- [1@2001-01-01, 2@2001-01-03)
      SELECT endSequence(tfloat '{[1@2001-01-01, 2@2001-01-03), [3@2001-01-03, 5@2001-01-05)}');
      -- [3@2001-01-03, 5@2001-01-05)
      SELECT sequenceN(tfloat '{[1@2001-01-01, 2@2001-01-03),
        [3@2001-01-03, 5@2001-01-05)}', 2);
      -- [3@2001-01-03, 5@2001-01-05)

- Devuelve los segmentos

  `segments({ttypeContSeq,ttypeSeqSet}) → ttypeContSeq[]`

      SELECT segments(tint '{[1@2001-01-01, 3@2001-01-02, 2@2001-01-03],
        (3@2001-01-03, 5@2001-01-05]}');
      /* {"[1@2001-01-01, 1@2001-01-02)","[3@2001-01-02, 3@2001-01-03)","[2@2001-01-03]",
         "(3@2001-01-03, 3@2001-01-05)","[5@2001-01-05]"} */
      SELECT segments(tfloat '{[1@2001-01-01, 3@2001-01-02, 2@2001-01-03],
        (3@2001-01-03, 5@2001-01-05]}');
      /* {"[1@2001-01-01, 3@2001-01-02)","[3@2001-01-02, 2@2001-01-03]",
         "(3@2001-01-03, 5@2001-01-05]"} */

## Transformaciones

Un valor temporal se puede transformar en otro subtipo. Se genera un error si los subtipos son incompatibles.

- Transformar un tipo temporal a otro subtipo

  `ttypeInst(ttype) → ttypeInst`

  `ttypeSeq(ttype) → ttypeSeq`

  `ttypeSeqSet(ttype) → ttypeSeqSet`

      SELECT tboolInst(tbool '{[true@2001-01-01]}');
      -- t@2001-01-01
      SELECT tboolInst(tbool '{[true@2001-01-01, true@2001-01-02]}');
      -- ERROR: Cannot transform input value to a temporal instant
      SELECT tintSeq(tint '1@2001-01-01');
      -- [1@2001-01-01]
      SELECT tfloatSeqSet(tfloat '2.5@2001-01-01');
      -- {[2.5@2001-01-01]}
      SELECT tfloatSeqSet(tfloat '{2.5@2001-01-01, 1.5@2001-01-02, 3.5@2001-01-03}');
      -- {[2.5@2001-01-01],[1.5@2001-01-02],[3.5@2001-01-03]}

- Transformar un valor temporal a otra interpolación

  `setInterp(ttype, interp) → ttype`

      SELECT setInterp(tbool 'true@2001-01-01','discrete');
      -- {t@2001-01-01}
      SELECT setInterp(tfloat '{[1@2001-01-01], [2@2001-01-02], [1@2001-01-03]}', 'discrete');
      -- {1@2001-01-01, 2@2001-01-02, 1@2001-01-03}
      SELECT setInterp(tfloat 'Interp=Step;[1@2001-01-01, 2@2001-01-02,
        1@2001-01-03, 2@2001-01-04]', 'linear');
      /* {[1@2001-01-01, 1@2001-01-02), [2@2001-01-02, 2@2001-01-03),
         [1@2001-01-03, 1@2001-01-04), [2@2001-01-04]} */
      SELECT asText(setInterp(tgeompoint 'Interp=Step;{[Point(1 1)@2001-01-01,
        Point(2 2)@2001-01-02], [Point(3 3)@2001-01-05, Point(4 4)@2001-01-06]}', 'linear'));
      /* {[POINT(1 1)@2001-01-01, POINT(1 1)@2001-01-02), [POINT(2 2)@2001-01-02],
         [POINT(3 3)@2001-01-05, POINT(3 3)@2001-01-06), [POINT(4 4)@2001-01-06]} */
      SELECT setInterp(tgeometry '[Point(1 1)@2001-01-01,
        Linestring(1 1,2 2)@2001-01-02]', 'linear');
      -- ERROR:  The temporal type cannot have linear interpolation

- Desplazar y/o escalear el intervalo de tiempo de un valor temporal a uno o dos intervalos

  `shiftTime(ttype,interval) → ttype`

  `scaleTime(ttype,interval) → ttype`

  `shiftScaleTime(ttype,interval,interval) → ttype`

  Cuando se escalea, si el rango de valores o el intervalo de tiempo del valor temporal es cero (por ejemplo, para un instante temporal), el resultado es el valor temporal. Igualmente, el ancho o intervalo dado debe ser estrictamente mayor que cero.

      SELECT shiftTime(tint '{1@2001-01-01, 2@2001-01-03, 1@2001-01-05}', '1 day');
      -- {1@2001-01-02, 2@2001-01-04, 1@2001-01-06}
      SELECT shiftTime(tfloat '[1@2001-01-01, 2@2001-01-03]', '1 day');
      -- [1@2001-01-02, 2@2001-01-04]
      SELECT asText(shiftTime(tgeompoint '{[Point(1 1)@2001-01-01, Point(2 2)@2001-01-03],
        [Point(2 2)@2001-01-04, Point(1 1)@2001-01-05]}', '1 day'));
      /* {[POINT(1 1)@2001-01-02, POINT(2 2)@2001-01-04],
         [POINT(2 2)@2001-01-05, POINT(1 1)@2001-01-06]} */
      SELECT scaleTime(tint '1@2001-01-01', '1 day');
      -- 1@2001-01-01
      SELECT scaleTime(tint '{1@2001-01-01, 2@2001-01-03, 1@2001-01-05}', '1 day');
      -- {1@2001-01-01 00:00:00+01, 2@2001-01-01 12:00:00+01, 1@2001-01-02 00:00:00+01}
      SELECT scaleTime(tfloat '[1@2001-01-01, 2@2001-01-03]', '1 day');
      -- [1@2001-01-01, 2@2001-01-02]
      SELECT asText(scaleTime(tgeompoint '{[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02,
        Point(1 1)@2001-01-03], [Point(2 2)@2001-01-04, Point(1 1)@2001-01-05]}', '1 day'));
      /* {[POINT(1 1)@2001-01-01 00:00:00+01, POINT(2 2)@2001-01-01 06:00:00+01,
         POINT(1 1)@2001-01-01 12:00:00+01], [POINT(2 2) @2001-01-01 18:00:00+01,
         POINT(1 1)@2001-01-02 00:00:00+01]} */
      SELECT scaleTime(tint '1@2001-01-01', '-1 day');
      -- ERROR:  The interval must be positive: -1 days
      SELECT shiftScaleTime(tint '1@2001-01-01', '1 day', '1 day');
      -- 1@2001-01-02
      SELECT shiftScaleTime(tint '{1@2001-01-01, 2@2001-01-03, 1@2001-01-05}', '1 day','1 day');
      -- {1@2001-01-02 00:00:00+01, 2@2001-01-02 12:00:00+01, 1@2001-01-03 00:00:00+01}
      SELECT shiftScaleTime(tfloat '[1@2001-01-01, 2@2001-01-03]', '1 day', '1 day');
      -- [1@2001-01-02, 2@2001-01-03]
      SELECT asText(shiftScaleTime(tgeometry '{[Point(1 1)@2001-01-01,
        Linestring(1 1,2 2)@2001-01-02, Point(1 1)@2001-01-03], [Point(2 2)@2001-01-04,
        Polygon((1 1,2 2,3 1,1 1))@2001-01-05]}', '1 day', '1 day'));
      /* {[POINT(1 1)@2001-01-02 00:00:00, LINESTRING(1 1,2 2)@2001-01-02 06:00:00,
          POINT(1 1)@2001-01-02 12:00:00], [POINT(2 2)@2001-01-02 18:00:00,
          POLYGON((1 1,2 2,3 1,1 1))@2001-01-03 00:00:00]} */

- Devuelve un valor booleano temporal que indica si cada segmento de una secuencia (o conjunto de sequencias) temporal(es) continua tiene, respectivamente, al menos o como máximo una duración determinada.

  `segmentMinDuration(temp,interval,bool strict=true) → tbool`

  `segmentMaxDuration(temp,interval,bool strict=true) → tbool`

  Si el argumento `strict` no se especifica, se asume el valor `true` por defecto y, por lo tanto, la función verifica si la duración del segmento es estrictamente menor o mayor que el intervalo. Si el argumento es `false`, la función verifica si la duración del segmento es menor/mayor o igual que el intervalo.

      SELECT segmentMinDuration(tfloat '[1@2001-01-01, 0@2001-01-03, -1@2001-01-04, -1@2001-01-06]', '1 day');
      -- {[t@2001-01-01, f@2001-01-03, t@2001-01-04, t@2001-01-06)}
      SELECT segmentMinDuration(tfloat '[1@2001-01-01, 0@2001-01-03, -1@2001-01-04, -1@2001-01-06]', '1 day', false);
      -- {[t@2001-01-01, t@2001-01-06)}
      SELECT segmentMaxDuration(tfloat '[1@2001-01-01, 0@2001-01-03, -1@2001-01-04, -1@2001-01-06]', '1 day');
      -- {[f@2001-01-01 00:00:00+01, f@2001-01-06 00:00:00+01)}
      SELECT segmentMaxDuration(tfloat '[1@2001-01-01, 0@2001-01-03, -1@2001-01-04, -1@2001-01-06]', '1 day', false);
      -- {[f@2001-01-01, t@2001-01-03, f@2001-01-04, f@2001-01-06)}

- Transformar un valor temporal no lineal en un conjunto de filas, cada una es una pareja compuesta de un valor de base y un conjunto de períodos durante el cual el valor temporal tiene el valor de base &SRF;

  `unnest(ttype) → {(value,time)}`

      SELECT (un).value, (un).time
      FROM (SELECT unnest(tfloat '{1@2001-01-01, 2@2001-01-02, 1@2001-01-03}') AS un) t;
      -- 1 | {[2001-01-01, 2001-01-01], [2001-01-03, 2001-01-03]}
      -- 2 | {[2001-01-02, 2001-01-02]}
      SELECT (un).value, (un).time
      FROM (SELECT unnest(tint '[1@2001-01-01, 2@2001-01-02, 1@2001-01-03]') AS un) t;
      -- 1 | {[2001-01-01, 2001-01-02), [2001-01-03, 2001-01-03]}
      -- 2 | {[2001-01-02, 2001-01-03)}
      SELECT (un).value, (un).time
      FROM (SELECT unnest(tfloat '[1@2001-01-01, 2@2001-01-02, 1@2001-01-03]') AS un) t;
      -- ERROR:  The temporal value cannot have linear interpolation
      SELECT ST_AsText((un).value), (un).time
      FROM (SELECT unnest(tgeompoint 'Interp=Step;[Point(1 1)@2001-01-01,
        Point(2 2)@2001-01-02, Point(1 1)@2001-01-03]') AS un) t;
      --  POINT(1 1) | {[2001-01-01, 2001-01-02), [2001-01-03, 2001-01-03]}
      --  POINT(2 2) | {[2001-01-02, 2001-01-03)}
      SELECT ST_AsText((un).value), (un).time
      FROM (SELECT unnest(tgeometry '[Point(1 1)@2001-01-01,
        Linestring(1 1,2 2)@2001-01-02, Point(1 1)@2001-01-03]') AS un) t;
      -- POINT(1 1)          | {[2001-01-01, 2001-01-02), [2001-01-03, 2001-01-03]}
      -- LINESTRING(1 1,2 2) | {[2001-01-02, 2001-01-03)}