CREATE EXTENSION pg_duration; -- Valid duration input CREATE TEMP TABLE input_table (s text); INSERT INTO input_table VALUES ('42 hour'), ('43 hours'), ('44 h'), ('45 minute'), ('46 minutes'), ('47 m'), ('48 second'), ('49 seconds'), ('50 s'), ('51 millisecond'), ('52 milliseconds'), ('53 ms'), ('54 microsecond'), ('55 microseconds'), ('56 us'), ('1 minute 2 h 3 microseconds 4 second 5 ms'); SELECT s, s::duration AS dur, ('-' || s)::duration AS neg_dur FROM input_table; SELECT duration '36 minutes ago'; SELECT duration '20:13:41'; SELECT duration 'PT20:13:41'; -- Invalid duration input SELECT duration '100 millennium'; SELECT duration '101 millenniums'; SELECT duration '102 century'; SELECT duration '103 centuries'; SELECT duration '104 decade'; SELECT duration '105 decades'; SELECT duration '106 year'; SELECT duration '107 years'; SELECT duration '108 y'; SELECT duration '109 month'; SELECT duration '110 months'; SELECT duration '111 week'; SELECT duration '112 weeks'; SELECT duration '113 w'; SELECT duration '114 day'; SELECT duration '115 days'; SELECT duration '116 d'; SELECT duration '5 seconds 2 days'; SELECT duration 'P1995-08-06T20:13:41'; -- Comparison CREATE TEMP TABLE cmp_table(a duration, b duration); INSERT INTO cmp_table VALUES ('1 sec', '1 hour'), ('1 millisecon', '1 ms'), ('1 minute', '1 us'); SELECT a, b, a < b AS lt, a <= b AS le, a > b AS gt, a >= b AS ge, a = b AS eq, a != b AS ne FROM cmp_table; -- Arithmetic -- Valid SELECT - duration '10 minutes'; SELECT duration '55 seconds' + duration '12 hours'; SELECT duration '2 hours' - duration '30 minutes'; SELECT duration '42 minutes' * 10.5; SELECT duration '42 minutes' * 0.0; SELECT duration '5 hours 40 minutes 30 s' / 3.7; -- Invalid SELECT - duration '-9223372036854775807 us'; SELECT duration '9223372036854775806 us' + duration '1 us'; SELECT duration '9223372036854775806 us' + duration '2 us'; SELECT duration '-9223372036854775807 us' - duration '1 us'; SELECT duration '-9223372036854775807 us' - duration '2 us'; SELECT duration '4611686018427387903 us' * 2.5; SELECT duration '4611686018427387903 us' * 'nan'::float8; SELECT duration '4611686018427387903 us' * 'infinity'::float8; SELECT duration '4611686018427387903 us' * '-infinity'::float8; SELECT duration '0 us' * 'infinity'::float8; SELECT duration '0 us' * '-infinity'::float8; SELECT duration '-4611686018427387904 us' / 0.5; SELECT duration '4611686018427387904 us' / 0.0; SELECT duration '4611686018427387904 us' / 'nan'::float8; SELECT duration '4611686018427387903 us' / 'infinity'::float8; SELECT duration '4611686018427387903 us' / '-infinity'::float8; -- Functions helper table CREATE TEMP TABLE valid_fields(f text); INSERT INTO valid_fields VALUES ('hour'), ('minute'), ('second'), ('millisecond'), ('microsecond'); CREATE TEMPORARY TABLE func_table (d duration); INSERT INTO func_table VALUES (duration '1 hour 2 minutes 3 seconds 4 milliseconds 5 microseconds'), (-duration '1 hour 2 minutes 3 seconds 4 milliseconds 5 microseconds'); -- make_duration SELECT make_duration(); SELECT make_duration(1); SELECT make_duration(1, 2); SELECT make_duration(1, 2, 3.456); SELECT make_duration(2147483647, 2147483647, 9223372036854775807); -- isfinite SELECT isfinite(duration '112 hours'); SELECT isfinite(duration 'infinity'); SELECT isfinite(duration '-infinity'); -- date_trunc SELECT f, d, date_trunc(f, d) FROM valid_fields, func_table; SELECT date_trunc('epoch', d) FROM func_table; SELECT date_trunc('millennium', d) FROM func_table; SELECT date_trunc('century', d) FROM func_table; SELECT date_trunc('decade', d) FROM func_table; SELECT date_trunc('year', d) FROM func_table; SELECT date_trunc('quarter', d) FROM func_table; SELECT date_trunc('month', d) FROM func_table; SELECT date_trunc('week', d) FROM func_table; SELECT date_trunc('day', d) FROM func_table; -- date_part SELECT f, d, date_part(f, d) FROM valid_fields, func_table; SELECT date_part('epoch', d) FROM func_table; SELECT date_part('millennium', d) FROM func_table; SELECT date_part('century', d) FROM func_table; SELECT date_part('decade', d) FROM func_table; SELECT date_part('year', d) FROM func_table; SELECT date_part('quarter', d) FROM func_table; SELECT date_part('month', d) FROM func_table; SELECT date_part('week', d) FROM func_table; SELECT date_part('day', d) FROM func_table; -- extract_duration SELECT f, d, extract_duration(f, d) FROM valid_fields, func_table; SELECT extract_duration('epoch', d) FROM func_table; SELECT extract_duration('millennium', d) FROM func_table; SELECT extract_duration('century', d) FROM func_table; SELECT extract_duration('decade', d) FROM func_table; SELECT extract_duration('year', d) FROM func_table; SELECT extract_duration('quarter', d) FROM func_table; SELECT extract_duration('month', d) FROM func_table; SELECT extract_duration('week', d) FROM func_table; SELECT extract_duration('day', d) FROM func_table; -- Casts -- Valid SELECT s, s::duration::interval AS interval, s::duration::interval::duration AS dur FROM (SELECT s FROM input_table UNION ALL SELECT '-' || s FROM input_table); -- Invalid SELECT (interval '1 month')::duration; SELECT (interval '1 day')::duration; SELECT (interval '1 month 2 days 3 hours')::duration; --- Aggregates SELECT avg(s::duration), count(s::duration), max(s::duration), min(s::duration), sum(s::duration) FROM ( SELECT s FROM input_table UNION ALL SELECT '-' || s FROM input_table UNION ALL SELECT NULL ); -- Infinity -- Create helper tables CREATE TEMP TABLE inf_table(d duration); INSERT INTO inf_table VALUES ('infinity'), ('-infinity'), ('999 hours'), ('-999 hours'); -- Input SELECT duration 'infinity'; SELECT duration '-infinity'; -- Comparison SELECT t1.d AS a, t2.d AS b, t1.d < t2.d AS lt, t1.d <= t2.d AS le, t1.d > t2.d AS gt, t1.d >= t2.d AS ge, t1.d = t2.d AS eq, t1.d != t2.d AS ne FROM inf_table AS t1, inf_table AS t2 WHERE NOT isfinite(t1.d) OR NOT isfinite(t2.d); -- Negation SELECT d, -d FROM inf_table WHERE NOT isfinite(d); -- Addition SELECT duration 'infinity' + duration '42 ms'; SELECT duration '-infinity' + duration '42 ms'; SELECT duration 'infinity' + duration 'infinity'; SELECT duration 'infinity' + duration '-infinity'; SELECT duration '-infinity' + duration 'infinity'; SELECT duration '-infinity' + duration '-infinity'; -- Subtraction SELECT duration 'infinity' - duration '42 ms'; SELECT duration '-infinity' - duration '42 ms'; SELECT duration 'infinity' - duration 'infinity'; SELECT duration 'infinity' - duration '-infinity'; SELECT duration '-infinity' - duration 'infinity'; SELECT duration '-infinity' - duration '-infinity'; -- Multiplication SELECT duration 'infinity' * 15.6; SELECT duration 'infinity' * -15.6; SELECT duration 'infinity' * 'infinity'::float8; SELECT duration 'infinity' * '-infinity'::float8; SELECT duration 'infinity' * 'nan'::float8; SELECT duration 'infinity' * 0.0; SELECT duration '-infinity' * 15.6; SELECT duration '-infinity' * -15.6; SELECT duration '-infinity' * 'infinity'::float8; SELECT duration '-infinity' * '-infinity'::float8; SELECT duration '-infinity' * 'nan'::float8; SELECT duration '-infinity' * 0.0; -- Division SELECT duration 'infinity' / 32.1; SELECT duration 'infinity' / -32.1; SELECT duration 'infinity' / 'infinity'::float8; SELECT duration 'infinity' / '-infinity'::float8; SELECT duration 'infinity' / 'nan'::float8; SELECT duration 'infinity' / 0.0; SELECT duration '-infinity' / 32.1; SELECT duration '-infinity' / -32.1; SELECT duration '-infinity' / 'infinity'::float8; SELECT duration '-infinity' / '-infinity'::float8; SELECT duration '-infinity' / 'nan'::float8; SELECT duration '-infinity' / 0.0; -- date_trunc SELECT f, d, date_trunc(f, d) FROM valid_fields, inf_table WHERE NOT isfinite(d); SELECT date_trunc('epoch', duration 'infinity'); SELECT date_trunc('millennium', duration 'infinity'); SELECT date_trunc('century', duration 'infinity'); SELECT date_trunc('decade', duration 'infinity'); SELECT date_trunc('year', duration 'infinity'); SELECT date_trunc('quarter', duration 'infinity'); SELECT date_trunc('month', duration 'infinity'); SELECT date_trunc('week', duration 'infinity'); SELECT date_trunc('day', duration 'infinity'); SELECT date_trunc('epoch', duration '-infinity'); SELECT date_trunc('millennium', duration '-infinity'); SELECT date_trunc('century', duration '-infinity'); SELECT date_trunc('decade', duration '-infinity'); SELECT date_trunc('year', duration '-infinity'); SELECT date_trunc('quarter', duration '-infinity'); SELECT date_trunc('month', duration '-infinity'); SELECT date_trunc('week', duration '-infinity'); SELECT date_trunc('day', duration '-infinity'); -- date_part SELECT f, d, date_part(f, d) FROM valid_fields, inf_table WHERE NOT isfinite(d); SELECT date_part('epoch', duration 'infinity'); SELECT date_part('millennium', duration 'infinity'); SELECT date_part('century', duration 'infinity'); SELECT date_part('decade', duration 'infinity'); SELECT date_part('year', duration 'infinity'); SELECT date_part('quarter', duration 'infinity'); SELECT date_part('month', duration 'infinity'); SELECT date_part('week', duration 'infinity'); SELECT date_part('day', duration 'infinity'); SELECT date_part('epoch', duration '-infinity'); SELECT date_part('millennium', duration '-infinity'); SELECT date_part('century', duration '-infinity'); SELECT date_part('decade', duration '-infinity'); SELECT date_part('year', duration '-infinity'); SELECT date_part('quarter', duration '-infinity'); SELECT date_part('month', duration '-infinity'); SELECT date_part('week', duration '-infinity'); SELECT date_part('day', duration '-infinity'); -- extract_duration SELECT f, d, extract_duration(f, d) FROM valid_fields, inf_table WHERE NOT isfinite(d); SELECT extract_duration('epoch', duration 'infinity'); SELECT extract_duration('millennium', duration 'infinity'); SELECT extract_duration('century', duration 'infinity'); SELECT extract_duration('decade', duration 'infinity'); SELECT extract_duration('year', duration 'infinity'); SELECT extract_duration('quarter', duration 'infinity'); SELECT extract_duration('month', duration 'infinity'); SELECT extract_duration('week', duration 'infinity'); SELECT extract_duration('day', duration 'infinity'); SELECT extract_duration('epoch', duration '-infinity'); SELECT extract_duration('millennium', duration '-infinity'); SELECT extract_duration('century', duration '-infinity'); SELECT extract_duration('decade', duration '-infinity'); SELECT extract_duration('year', duration '-infinity'); SELECT extract_duration('quarter', duration '-infinity'); SELECT extract_duration('month', duration '-infinity'); SELECT extract_duration('week', duration '-infinity'); SELECT extract_duration('day', duration '-infinity'); -- Casts SELECT d, d::INTERVAL AS interval, d::INTERVAL::duration AS dur FROM inf_table WHERE NOT isfinite(d); -- Aggregates SELECT avg(d), max(d), min(d), sum(d) FROM inf_table WHERE d != duration 'infinity'; SELECT avg(d), max(d), min(d), sum(d) FROM inf_table WHERE d != duration '-infinity'; SELECT max(d), min(d) FROM inf_table; SELECT avg(d) FROM inf_table; SELECT sum(d) FROM inf_table; -- Overflow SELECT duration '9223372036854775807 us'; SELECT duration '-9223372036854775808 us'; -- Inserts and indexes DROP SCHEMA IF EXISTS regress CASCADE; CREATE SCHEMA regress; CREATE TABLE regress.t (d1 duration, d2 duration); CREATE INDEX idx1 ON regress.t USING BTREE (d1); CREATE INDEX idx2 ON regress.t USING HASH (d2); INSERT INTO regress.t VALUES ('1 s 6 m', '5 us'), ('500ms 4 h', '42 seconds 3 us'), ('666 hours', '999 min'); SELECT * FROM regress.t; SELECT d1 FROM regress.t WHERE d1 > '1 hour'; SELECT d2 FROM regress.t WHERE d2 = '42 seconds 3 microseconds'; DROP SCHEMA regress CASCADE;