# Note that the odd '0000-01-01 hh:mi:ss +0000 UTC' result format is an
# artifact of how pq displays TIMEs.

query T
SELECT '12:00:00':::TIME;
----
0000-01-01 12:00:00 +0000 UTC

query T
SELECT '12:00:00.456':::TIME;
----
0000-01-01 12:00:00.456 +0000 UTC

query T
SELECT '00:00:00':::TIME;
----
0000-01-01 00:00:00 +0000 UTC

query T
SELECT '23:59:59.999999':::TIME;
----
0000-01-01 23:59:59.999999 +0000 UTC

query T
select ('24:00'::TIME)::STRING
----
24:00:00

query T
SELECT ('24:00:00'::TIME)::STRING
----
24:00:00

statement error could not parse
SELECT '124:00'::TIME;

statement error could not parse
SELECT '24:00:01'::TIME;

statement error could not parse
SELECT '24:00:00.001'::TIME;


# Timezone should be ignored.
query T
SELECT '12:00:00-08:00':::TIME;
----
0000-01-01 12:00:00 +0000 UTC

query T
SELECT TIME '12:00:00';
----
0000-01-01 12:00:00 +0000 UTC

# Casting

query T
SELECT '12:00:00'::TIME;
----
0000-01-01 12:00:00 +0000 UTC

query T
select '12:00:00':::STRING::TIME;
----
0000-01-01 12:00:00 +0000 UTC

query T
SELECT '12:00:00' COLLATE de::TIME;
----
0000-01-01 12:00:00 +0000 UTC

query T
SELECT '2017-01-01 12:00:00':::TIMESTAMP::TIME;
----
0000-01-01 12:00:00 +0000 UTC

query T
SELECT '2017-01-01 12:00:00-05':::TIMESTAMPTZ::TIME;
----
0000-01-01 17:00:00 +0000 UTC

query T
SELECT '12h':::INTERVAL::TIME;
----
0000-01-01 12:00:00 +0000 UTC

query T
SELECT '12:00:00':::TIME::INTERVAL;
----
12:00:00

query T
SELECT '12:00:00':::TIME::STRING;
----
12:00:00

# Comparison

query B
SELECT '12:00:00':::TIME = '12:00:00':::TIME
----
true

query B
SELECT '12:00:00':::TIME = '12:00:00.000000':::TIME
----
true

query B
SELECT '12:00:00':::TIME = '12:00:00.000001':::TIME
----
false

query B
SELECT '12:00:00':::TIME < '12:00:00.000001':::TIME
----
true

query B
SELECT '12:00:00':::TIME < '12:00:00':::TIME
----
false

query B
SELECT '12:00:00':::TIME < '11:59:59.999999':::TIME
----
false

query B
SELECT '12:00:00':::TIME > '11:59:59.999999':::TIME
----
true

query B
SELECT '12:00:00':::TIME > '12:00:00':::TIME
----
false

query B
SELECT '12:00:00':::TIME > '12:00:00.000001':::TIME
----
false

query B
SELECT '12:00:00':::TIME <= '12:00:00':::TIME
----
true

query B
SELECT '12:00:00':::TIME >= '12:00:00':::TIME
----
true

query B
SELECT '12:00:00':::TIME IN ('12:00:00');
----
true

query B
SELECT '12:00:00':::TIME IN ('00:00:00');
----
false

# Arithmetic

query T
SELECT '12:00:00':::TIME + '1s':::INTERVAL
----
0000-01-01 12:00:01 +0000 UTC

query T
SELECT '23:59:59':::TIME + '1s':::INTERVAL
----
0000-01-01 00:00:00 +0000 UTC

query T
SELECT '12:00:00':::TIME + '1d':::INTERVAL
----
0000-01-01 12:00:00 +0000 UTC

query T
SELECT '1s':::INTERVAL + '12:00:00':::TIME
----
0000-01-01 12:00:01 +0000 UTC

query T
SELECT '12:00:00':::TIME - '1s':::INTERVAL
----
0000-01-01 11:59:59 +0000 UTC

query T
SELECT '00:00:00':::TIME - '1s':::INTERVAL
----
0000-01-01 23:59:59 +0000 UTC

query T
SELECT '12:00:00':::TIME - '1d':::INTERVAL
----
0000-01-01 12:00:00 +0000 UTC

query T
SELECT '12:00:00':::TIME - '11:59:59':::TIME
----
00:00:01

query T
SELECT '11:59:59':::TIME - '12:00:00':::TIME
----
-00:00:01

query T
SELECT '2017-01-01':::DATE + '12:00:00':::TIME
----
2017-01-01 12:00:00 +0000 +0000

query T
SELECT '12:00:00':::TIME + '2017-01-01':::DATE
----
2017-01-01 12:00:00 +0000 +0000

query T
SELECT '2017-01-01':::DATE - '12:00:00':::TIME
----
2016-12-31 12:00:00 +0000 +0000

# Storage

statement ok
CREATE TABLE times (t time PRIMARY KEY)

statement ok
INSERT INTO times VALUES
  ('00:00:00'),
  ('00:00:00.000001'),
  ('11:59:59.999999'),
  ('12:00:00'),
  ('12:00:00.000001'),
  ('23:59:59.999999')

query T
SELECT * FROM times ORDER BY t
----
0000-01-01 00:00:00 +0000 UTC
0000-01-01 00:00:00.000001 +0000 UTC
0000-01-01 11:59:59.999999 +0000 UTC
0000-01-01 12:00:00 +0000 UTC
0000-01-01 12:00:00.000001 +0000 UTC
0000-01-01 23:59:59.999999 +0000 UTC

statement ok
CREATE TABLE arrays (times TIME[])

statement ok
INSERT INTO arrays VALUES
  (ARRAY[]),
  (ARRAY['00:00:00']),
  (ARRAY['00:00:00', '12:00:00.000001']),
  ('{13:00:00}'::TIME[])

query T rowsort
SELECT * FROM arrays
----
{}
{00:00:00}
{00:00:00,12:00:00.000001}
{13:00:00}

# Built-ins

query T
SELECT date_trunc('hour', time '12:01:02.345678')
----
12:00:00

query T
SELECT date_trunc('minute', time '12:01:02.345678')
----
12:01:00

query T
SELECT date_trunc('second', time '12:01:02.345678')
----
12:01:02

query T
SELECT date_trunc('millisecond', time '12:01:02.345678')
----
12:01:02.345

query T
SELECT date_trunc('microsecond', time '12:01:02.345678')
----
12:01:02.345678

query error pgcode 22023 date_trunc\(\): unsupported timespan: day
SELECT date_trunc('day', time '12:01:02.345')

query R
SELECT extract(hour from time '12:01:02.345678')
----
12

query R
SELECT extract(minute from time '12:01:02.345678')
----
1

query R
SELECT extract(second from time '12:01:02.345678')
----
2.345678

query R
SELECT extract(millisecond from time '12:01:02.345678')
----
2345.678

query R
SELECT extract(microsecond from time '12:01:02.345678')
----
2.345678e+06

query R
SELECT extract(epoch from time '12:00:00')
----
43200

query error pgcode 22023 extract\(\): unsupported timespan: day
SELECT extract(day from time '12:00:00')

query R
SELECT extract('microsecond' from time '12:01:02.345678')
----
2.345678e+06

query R
SELECT extract('EPOCH' from time '12:00:00')
----
43200

query error pgcode 22023 extract\(\): unsupported timespan: day
SELECT extract('day' from time '12:00:00')

query error pgcode 22023 extract\(\): unsupported timespan: day
SELECT extract('DAY' from time '12:00:00')

subtest precision_tests

query error precision 7 out of range
select '1:00:00.001':::TIME(7)

statement ok
CREATE TABLE time_precision_test (
  id integer PRIMARY KEY,
  t TIME(5)
)

statement ok
INSERT INTO time_precision_test VALUES
  (1,'12:00:00.123456+03:00'),
  (2,'12:00:00.12345+03:00'),
  (3,'12:00:00.1234+03:00'),
  (4,'12:00:00.123+03:00'),
  (5,'12:00:00.12+03:00'),
  (6,'12:00:00.1+03:00'),
  (7,'12:00:00+03:00')

query IT
SELECT * FROM time_precision_test ORDER BY id ASC
----
1  0000-01-01 12:00:00.12346 +0000 UTC
2  0000-01-01 12:00:00.12345 +0000 UTC
3  0000-01-01 12:00:00.1234 +0000 UTC
4  0000-01-01 12:00:00.123 +0000 UTC
5  0000-01-01 12:00:00.12 +0000 UTC
6  0000-01-01 12:00:00.1 +0000 UTC
7  0000-01-01 12:00:00 +0000 UTC

query TT
select column_name, data_type FROM [SHOW COLUMNS FROM time_precision_test] ORDER BY column_name
----
id  INT8
t   TIME(5)

statement ok
ALTER TABLE time_precision_test ALTER COLUMN t TYPE time(6)

statement ok
INSERT INTO time_precision_test VALUES
  (100,'12:00:00.123456+03:00')

query IT
SELECT * FROM time_precision_test ORDER BY id ASC
----
1    0000-01-01 12:00:00.12346 +0000 UTC
2    0000-01-01 12:00:00.12345 +0000 UTC
3    0000-01-01 12:00:00.1234 +0000 UTC
4    0000-01-01 12:00:00.123 +0000 UTC
5    0000-01-01 12:00:00.12 +0000 UTC
6    0000-01-01 12:00:00.1 +0000 UTC
7    0000-01-01 12:00:00 +0000 UTC
100  0000-01-01 12:00:00.123456 +0000 UTC

query TT
select column_name, data_type FROM [SHOW COLUMNS FROM time_precision_test] ORDER BY column_name
----
id  INT8
t   TIME(6)

subtest localtime_test

query B
select localtime(3) - localtime <= '1ms'::interval
----
true

query TTTT
select pg_typeof(localtime), pg_typeof(current_time), pg_typeof(localtime(3)), pg_typeof(current_time(3))
----
time without time zone  time with time zone  time without time zone  time with time zone

subtest regression_42749

# cast to string to prove it is 24:00
query T
SELECT '0000-01-01 24:00:00'::time::string
----
24:00:00

query T
SELECT '2001-01-01 01:24:00'::time
----
0000-01-01 01:24:00 +0000 UTC

subtest current_time_tests

statement ok
CREATE TABLE current_time_test (
  id INTEGER PRIMARY KEY,
  a TIME(3) DEFAULT CURRENT_TIME,
  b TIME DEFAULT CURRENT_TIME
)

statement ok
INSERT INTO current_time_test (id) VALUES (1)

statement ok
INSERT INTO current_time_test (id, a, b) VALUES
  (2, current_time, current_time),
  (3, current_time, current_time(3)),
  (4, localtime, localtime(3))

query I
SELECT id FROM current_time_test WHERE
  ('1970-01-01 ' || b::string)::timestamp -
  ('1970-01-01 ' || a::string)::timestamp
> '1ms'::interval ORDER BY id ASC
----

# test that current_time is correct in different timezones.
statement ok
set time zone +3

statement ok
create table current_time_tzset_test (id integer, a time, b time)

statement ok
insert into current_time_tzset_test (id, a) values (1, current_time), (2, localtime)

statement ok
set time zone 0

statement ok
update current_time_tzset_test set b = current_time where id = 1

statement ok
update current_time_tzset_test set b = localtime where id = 2

# a was written at an interval 3 hours ahead, and should persist that way.
# make sure they're roughly 3 hours apart.
# note time can overflow and result in negative duration,
# so test both 3 hour and -21 hour cases.
query I
select id from current_time_tzset_test WHERE
  ((a - b) BETWEEN interval '2hr 59m' and interval '3h') OR
  ((a - b) BETWEEN interval '-21hr -1m' and interval '-21hr')
ORDER BY id ASC
----
1
2

# Check default types and expressions get truncated on insert / update.
subtest regression_44774

statement ok
CREATE TABLE regression_44774 (
  a time(3) DEFAULT '12:13:14.123456'
)

statement ok
INSERT INTO regression_44774 VALUES (default), ('19:21:57.261286')

query T
SELECT a FROM regression_44774 ORDER BY a
----
0000-01-01 12:13:14.123 +0000 UTC
0000-01-01 19:21:57.261 +0000 UTC

statement ok
UPDATE regression_44774
SET a = '13:14:15.123456'::time + '1 sec'::interval
WHERE 1 = 1

query T
SELECT a FROM regression_44774 ORDER BY a
----
0000-01-01 13:14:16.123 +0000 UTC
0000-01-01 13:14:16.123 +0000 UTC

statement ok
DROP TABLE regression_44774

subtest regression_46973

statement ok
CREATE TABLE regression_46973 (a TIME UNIQUE)

statement ok
INSERT INTO regression_46973 VALUES ('23:59:59.999999'), ('24:00')

query T
SELECT * FROM regression_46973 WHERE a != '23:59:59.999999'
----
0000-01-02 00:00:00 +0000 UTC

query T
SELECT * FROM regression_46973 WHERE a != '24:00'
----
0000-01-01 23:59:59.999999 +0000 UTC

statement ok
DROP TABLE regression_46973

subtest regression_88128

statement ok
CREATE TABLE t88128 (t TIME)

statement ok
INSERT INTO t88128 VALUES ('20:00:00')

# Ensure that the optimizer does not simplify the filter by adding the constant
# subtrahend to the right side of the comparison when the addition would
# overflow.
query B
SELECT t - '05:00:00'::INTERVAL < '23:59:00'::TIME FROM t88128
----
true

# Ensure that the optimizer does not simplify the filter by adding the constant
# subtrahend to the right side of the comparison when the addition would
# underflow.
query B
SELECT t - '-2:00:00'::INTERVAL > '01:00:00'::TIME FROM t88128
----
true

# Ensure that the optimizer does not simplify the filter by subtracting the
# constant addend to the right side of the comparison when the subtraction would
# underflow.
query B
SELECT t + '02:00:00'::INTERVAL > '01:00:00'::TIME FROM t88128
----
true

# Ensure that the optimizer does not simplify the filter by subtracting the
# constant addend to the right side of the comparison when the subtraction would
# overflow.
query B
SELECT t + '-18:00:00'::INTERVAL < '07:00:00'::TIME FROM t88128
----
true

subtest regression_90053

# Regression tests for #90053. Do not normalize comparisons with constants when
# addition/subtraction of the types involved could overflow without an error.
query B
SELECT '00:01:40.01+09:00:00' < (col::TIMETZ + '-83 years -1 mons -38 days -10:32:23.707137')
FROM (VALUES ('03:16:01.252182+01:49:00')) v(col);
----
true

query B
SELECT t::TIME + '-11 hrs'::INTERVAL > '01:00'::TIME
FROM (VALUES ('03:00')) v(t)
----
true
