diff --git a/core/src/main/java/org/opensearch/sql/expression/DSL.java b/core/src/main/java/org/opensearch/sql/expression/DSL.java index f5fd1e33153..1373f46273e 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -387,7 +387,12 @@ public static FunctionExpression time_to_sec(Expression... expressions) { } public static FunctionExpression timestamp(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.TIMESTAMP, expressions); + return timestamp(FunctionProperties.None, expressions); + } + + public static FunctionExpression timestamp(FunctionProperties functionProperties, + Expression... expressions) { + return compile(functionProperties, BuiltinFunctionName.TIMESTAMP, expressions); } public static FunctionExpression date_format(Expression... expressions) { diff --git a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java index df4dd0a96b5..a2edbf03581 100644 --- a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java @@ -631,15 +631,72 @@ private DefaultFunctionResolver time_to_sec() { /** * Extracts the timestamp of a date and time value. - * Also to construct a date type. The supported signatures: - * STRING/DATE/DATETIME/TIMESTAMP -> DATE + * Input strings may contain a timestamp only in format 'yyyy-MM-dd HH:mm:ss[.SSSSSSSSS]' + * STRING/DATE/TIME/DATETIME/TIMESTAMP -> TIMESTAMP + * STRING/DATE/TIME/DATETIME/TIMESTAMP, STRING/DATE/TIME/DATETIME/TIMESTAMP -> TIMESTAMP */ private DefaultFunctionResolver timestamp() { return define(BuiltinFunctionName.TIMESTAMP.getName(), - impl(nullMissingHandling(DateTimeFunction::exprTimestamp), TIMESTAMP, STRING), - impl(nullMissingHandling(DateTimeFunction::exprTimestamp), TIMESTAMP, DATE), - impl(nullMissingHandling(DateTimeFunction::exprTimestamp), TIMESTAMP, DATETIME), - impl(nullMissingHandling(DateTimeFunction::exprTimestamp), TIMESTAMP, TIMESTAMP)); + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestamp), + TIMESTAMP, STRING), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestamp), + TIMESTAMP, DATE), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestamp), + TIMESTAMP, TIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestamp), + TIMESTAMP, DATETIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestamp), + TIMESTAMP, TIMESTAMP), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, STRING, STRING), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, STRING, DATE), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, STRING, TIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, STRING, DATETIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, STRING, TIMESTAMP), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATE, STRING), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATE, DATE), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATE, TIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATE, DATETIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATE, TIMESTAMP), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIME, STRING), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIME, DATE), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIME, TIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIME, DATETIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIME, TIMESTAMP), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATETIME, STRING), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATETIME, DATE), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATETIME, TIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATETIME, DATETIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, DATETIME, TIMESTAMP), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIMESTAMP, STRING), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIMESTAMP, DATE), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIMESTAMP, TIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIMESTAMP, DATETIME), + implWithProperties(nullMissingHandlingWithProperties(DateTimeFunction::exprTimestampEx), + TIMESTAMP, TIMESTAMP, TIMESTAMP)); } /** @@ -1185,15 +1242,29 @@ private ExprValue exprTime(ExprValue exprValue) { /** * Timestamp implementation for ExprValue. * - * @param exprValue ExprValue of Timestamp type or String type. + * @param exprValue ExprValue of Timestamp. * @return ExprValue. */ - private ExprValue exprTimestamp(ExprValue exprValue) { + private ExprValue exprTimestamp(FunctionProperties functionProperties, ExprValue exprValue) { if (exprValue instanceof ExprStringValue) { return new ExprTimestampValue(exprValue.stringValue()); - } else { - return new ExprTimestampValue(exprValue.timestampValue()); } + return new ExprTimestampValue(DateTimeUtils.extractTimestamp(exprValue, functionProperties)); + } + + /** + * Timestamp implementation for two arguments. It extracts time expression from exprValue2 + * and adds it to the expression exprValue1 and returns the result as a timestamp value. + * + * @param exprValue1 ExprValue of Timestamp type or String type. + * @param exprValue2 ExprValue of Timestamp type or String type. + * @return ExprValue. + */ + private ExprValue exprTimestampEx(FunctionProperties functionProperties, + ExprValue exprValue1, ExprValue exprValue2) { + return exprAddTime(functionProperties, + exprTimestamp(functionProperties, exprValue1), + exprTimestamp(functionProperties, exprValue2)); } /** diff --git a/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java b/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java index 6ca9486de61..0f8a81fd372 100644 --- a/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java +++ b/core/src/main/java/org/opensearch/sql/utils/DateTimeUtils.java @@ -139,4 +139,15 @@ public static LocalDateTime extractDateTime(ExprValue value, ? ((ExprTimeValue) value).datetimeValue(functionProperties) : value.datetimeValue(); } + + /** + * Extracts Instant from a datetime ExprValue. + * Uses `FunctionProperties` for `ExprTimeValue`. + */ + public static Instant extractTimestamp(ExprValue value, + FunctionProperties functionProperties) { + return value instanceof ExprTimeValue + ? ((ExprTimeValue) value).timestampValue(functionProperties) + : value.timestampValue(); + } } diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/TimestampTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/TimestampTest.java new file mode 100644 index 00000000000..98c4332b17c --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/TimestampTest.java @@ -0,0 +1,186 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.expression.datetime; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.opensearch.sql.data.model.ExprTimestampValue; +import org.opensearch.sql.data.model.ExprValueUtils; +import org.opensearch.sql.exception.SemanticCheckException; +import org.opensearch.sql.expression.DSL; +import org.opensearch.sql.expression.ExpressionTestBase; + +public class TimestampTest extends ExpressionTestBase { + + @Test + public void timestamp_one_arg_string() { + var expr = DSL.timestamp(functionProperties, DSL.literal("1961-04-12 09:07:00")); + assertEquals(TIMESTAMP, expr.type()); + assertEquals(new ExprTimestampValue("1961-04-12 09:07:00"), expr.valueOf()); + + expr = DSL.timestamp(functionProperties, DSL.literal("1961-04-12 09:07:00.123456")); + assertEquals(TIMESTAMP, expr.type()); + assertEquals(LocalDateTime.of(1961, 4, 12, 9, 7, 0, 123456000), + expr.valueOf().datetimeValue()); + } + + /** + * Check that `TIMESTAMP` function throws an exception on incorrect string input. + * @param value A value. + * @param testName A test name. + */ + @ParameterizedTest(name = "{1}") + @CsvSource({ + "1984-02-30 12:20:42, Feb 30th", + "1984-02-10 24:00:00, 24:00:00", + "84-02-10 12:20:42, 2 digit year" + }) + public void timestamp_one_arg_string_invalid_format(String value, String testName) { + // exception thrown from ExprTimestampValue(String) CTOR + var exception = assertThrows(SemanticCheckException.class, + () -> DSL.timestamp(functionProperties, DSL.literal(value)).valueOf()); + assertEquals(String.format("timestamp:%s in unsupported format, please " + + "use yyyy-MM-dd HH:mm:ss[.SSSSSSSSS]", value), exception.getMessage()); + } + + @Test + public void timestamp_one_arg_time() { + var expr = DSL.timestamp(functionProperties, DSL.time(DSL.literal("22:33:44"))); + assertEquals(TIMESTAMP, expr.type()); + var refValue = LocalDate.now().atTime(LocalTime.of(22, 33, 44)) + .atZone(ExprTimestampValue.ZONE).toInstant(); + assertEquals(new ExprTimestampValue(refValue), expr.valueOf()); + } + + @Test + public void timestamp_one_arg_date() { + var expr = DSL.timestamp(functionProperties, DSL.date(DSL.literal("2077-12-15"))); + assertEquals(TIMESTAMP, expr.type()); + var refValue = LocalDate.of(2077, 12, 15).atStartOfDay() + .atZone(ExprTimestampValue.ZONE).toInstant(); + assertEquals(new ExprTimestampValue(refValue), expr.valueOf()); + } + + @Test + public void timestamp_one_arg_datetime() { + var expr = DSL.timestamp(functionProperties, DSL.datetime(DSL.literal("1961-04-12 09:07:00"))); + assertEquals(TIMESTAMP, expr.type()); + assertEquals(LocalDateTime.of(1961, 4, 12, 9, 7, 0), expr.valueOf().datetimeValue()); + } + + @Test + public void timestamp_one_arg_timestamp() { + var refValue = new ExprTimestampValue(Instant.ofEpochSecond(10050042)); + var expr = DSL.timestamp(functionProperties, + DSL.timestamp(functionProperties, DSL.literal(refValue))); + assertEquals(TIMESTAMP, expr.type()); + assertEquals(refValue, expr.valueOf()); + } + + private static Instant dateTime2Instant(LocalDateTime dt) { + return dt.atZone(ExprTimestampValue.ZONE).toInstant(); + } + + private static ExprTimestampValue dateTime2ExprTs(LocalDateTime dt) { + return new ExprTimestampValue(dateTime2Instant(dt)); + } + + private static Stream getTestData() { + var today = LocalDate.now(); + // First argument of `TIMESTAMP` function, second argument and expected result value + return Stream.of( + // STRING and STRING/DATE/TIME/DATETIME/TIMESTAMP + Arguments.of("1961-04-12 09:07:00", "2077-12-15 01:48:00", + dateTime2ExprTs(LocalDateTime.of(1961, 4, 12, 10, 55, 0))), + Arguments.of("1984-02-10 12:20:42", LocalDate.of(2077, 12, 21), + dateTime2ExprTs(LocalDateTime.of(1984, 2, 10, 12, 20, 42))), + Arguments.of("1961-04-12 09:07:00", LocalTime.of(1, 48), + dateTime2ExprTs(LocalDateTime.of(1961, 4, 12, 10, 55, 0))), + Arguments.of("2020-12-31 17:30:00", LocalDateTime.of(2077, 12, 21, 12, 20, 42), + dateTime2ExprTs(LocalDateTime.of(2021, 1, 1, 5, 50, 42))), + Arguments.of("2020-12-31 17:30:00", Instant.ofEpochSecond(42), + dateTime2ExprTs(LocalDateTime.of(2020, 12, 31, 17, 30, 42))), + // DATE and STRING/DATE/TIME/DATETIME/TIMESTAMP + Arguments.of(LocalDate.of(2077, 12, 21), "2077-12-15 01:48:00", + dateTime2ExprTs(LocalDateTime.of(2077, 12, 21, 1, 48, 0))), + Arguments.of(LocalDate.of(2077, 12, 21), LocalDate.of(1984, 2, 3), + dateTime2ExprTs(LocalDateTime.of(2077, 12, 21, 0, 0, 0))), + Arguments.of(LocalDate.of(2077, 12, 21), LocalTime.of(22, 33, 44), + dateTime2ExprTs(LocalDateTime.of(2077, 12, 21, 22, 33, 44))), + Arguments.of(LocalDate.of(2077, 12, 21), LocalDateTime.of(1999, 9, 9, 22, 33, 44), + dateTime2ExprTs(LocalDateTime.of(2077, 12, 21, 22, 33, 44))), + Arguments.of(LocalDate.of(2077, 12, 21), Instant.ofEpochSecond(42), + dateTime2ExprTs(LocalDateTime.of(2077, 12, 21, 0, 0, 42))), + // TIME and STRING/DATE/TIME/DATETIME/TIMESTAMP + Arguments.of(LocalTime.of(9, 7, 0), "2077-12-15 01:48:00", + dateTime2ExprTs(today.atTime(LocalTime.of(10, 55, 0)))), + Arguments.of(LocalTime.of(12, 20, 42), LocalDate.of(2077, 12, 21), + dateTime2ExprTs(today.atTime(LocalTime.of(12, 20, 42)))), + Arguments.of(LocalTime.of(9, 7, 0), LocalTime.of(1, 48), + dateTime2ExprTs(today.atTime(LocalTime.of(10, 55, 0)))), + Arguments.of(LocalTime.of(17, 30, 0), LocalDateTime.of(2077, 12, 21, 12, 20, 42), + dateTime2ExprTs(today.plusDays(1).atTime(LocalTime.of(5, 50, 42)))), + Arguments.of(LocalTime.of(17, 30, 0), Instant.ofEpochSecond(42), + dateTime2ExprTs(today.atTime(LocalTime.of(17, 30, 42)))), + // DATETIME and STRING/DATE/TIME/DATETIME/TIMESTAMP + Arguments.of(LocalDateTime.of(1961, 4, 12, 9, 7, 0), "2077-12-15 01:48:00", + dateTime2ExprTs(LocalDateTime.of(1961, 4, 12, 10, 55, 0))), + Arguments.of(LocalDateTime.of(1984, 2, 10, 12, 20, 42), LocalDate.of(2077, 12, 21), + dateTime2ExprTs(LocalDateTime.of(1984, 2, 10, 12, 20, 42))), + Arguments.of(LocalDateTime.of(1961, 4, 12, 9, 7, 0), LocalTime.of(1, 48), + dateTime2ExprTs(LocalDateTime.of(1961, 4, 12, 10, 55, 0))), + Arguments.of(LocalDateTime.of(2020, 12, 31, 17, 30, 0), + LocalDateTime.of(2077, 12, 21, 12, 20, 42), + dateTime2ExprTs(LocalDateTime.of(2021, 1, 1, 5, 50, 42))), + Arguments.of(LocalDateTime.of(2020, 12, 31, 17, 30, 0), Instant.ofEpochSecond(42), + dateTime2ExprTs(LocalDateTime.of(2020, 12, 31, 17, 30, 42))), + // TIMESTAMP and STRING/DATE/TIME/DATETIME/TIMESTAMP + Arguments.of(dateTime2Instant(LocalDateTime.of(1961, 4, 12, 9, 7, 0)), + "2077-12-15 01:48:00", + dateTime2ExprTs(LocalDateTime.of(1961, 4, 12, 10, 55, 0))), + Arguments.of(dateTime2Instant(LocalDateTime.of(1984, 2, 10, 12, 20, 42)), + LocalDate.of(2077, 12, 21), + dateTime2ExprTs(LocalDateTime.of(1984, 2, 10, 12, 20, 42))), + Arguments.of(dateTime2Instant(LocalDateTime.of(1961, 4, 12, 9, 7, 0)), + LocalTime.of(1, 48), + dateTime2ExprTs(LocalDateTime.of(1961, 4, 12, 10, 55, 0))), + Arguments.of(dateTime2Instant(LocalDateTime.of(2020, 12, 31, 17, 30, 0)), + LocalDateTime.of(2077, 12, 21, 12, 20, 42), + dateTime2ExprTs(LocalDateTime.of(2021, 1, 1, 5, 50, 42))), + Arguments.of(dateTime2Instant(LocalDateTime.of(2020, 12, 31, 17, 30, 0)), + Instant.ofEpochSecond(42), + dateTime2ExprTs(LocalDateTime.of(2020, 12, 31, 17, 30, 42))) + ); + } + + /** + * Test `TIMESTAMP` function which takes 2 arguments with input of different types. + * @param arg1 First argument to be passed to `TIMESTAMP` function. + * @param arg2 Second argument to be passed to `TIMESTAMP` function. + * @param expected The expected result. + */ + @ParameterizedTest + @MethodSource("getTestData") + public void timestamp_with_two_args(Object arg1, Object arg2, ExprTimestampValue expected) { + var expr = DSL.timestamp(functionProperties, + DSL.literal(ExprValueUtils.fromObjectValue(arg1)), + DSL.literal(ExprValueUtils.fromObjectValue(arg2))); + assertEquals(TIMESTAMP, expr.type()); + assertEquals(expected, expr.valueOf()); + } +} diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index f7383d862d5..9144ec420bf 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -1172,9 +1172,9 @@ Argument type: DATETIME/STRING Return type map: -DATETIME, STRING -> DATETIME +(DATETIME, STRING) -> DATETIME -DATETIME -> DATETIME +(DATETIME) -> DATETIME Example:: @@ -2167,21 +2167,26 @@ TIMESTAMP Description >>>>>>>>>>> -Usage: timestamp(expr) construct a timestamp type with the input string expr as an timestamp. If the argument is of date/datetime/timestamp type, cast expr to timestamp type with default timezone UTC. +Usage: timestamp(expr) constructs a timestamp type with the input string `expr` as an timestamp. If the argument is not a string, it casts `expr` to timestamp type with default timezone UTC. If argument is a time, it applies today's date before cast. +With two arguments `timestamp(expr1, expr2)` adds the time expression `expr2` to the date or datetime expression `expr1` and returns the result as a timestamp value. -Argument type: STRING/DATE/DATETIME/TIMESTAMP +Argument type: STRING/DATE/TIME/DATETIME/TIMESTAMP + +Return type map: + +(STRING/DATE/TIME/DATETIME/TIMESTAMP) -> TIMESTAMP -Return type: TIMESTAMP +(STRING/DATE/TIME/DATETIME/TIMESTAMP, STRING/DATE/TIME/DATETIME/TIMESTAMP) -> TIMESTAMP Example:: - >od SELECT TIMESTAMP('2020-08-26 13:49:00') + os> SELECT TIMESTAMP('2020-08-26 13:49:00'), TIMESTAMP('2020-08-26 13:49:00', TIME('12:15:42')) fetched rows / total rows = 1/1 - +------------------------------------+ - | TIMESTAMP('2020-08-26 13:49:00') | - |------------------------------------| - | TIMESTAMP '2020-08-26 13:49:00 | - +------------------------------------+ + +------------------------------------+------------------------------------------------------+ + | TIMESTAMP('2020-08-26 13:49:00') | TIMESTAMP('2020-08-26 13:49:00', TIME('12:15:42')) | + |------------------------------------+------------------------------------------------------| + | 2020-08-26 13:49:00 | 2020-08-27 02:04:42 | + +------------------------------------+------------------------------------------------------+ TO_DAYS diff --git a/docs/user/ppl/functions/datetime.rst b/docs/user/ppl/functions/datetime.rst index 2cc83eba971..cef46cd1844 100644 --- a/docs/user/ppl/functions/datetime.rst +++ b/docs/user/ppl/functions/datetime.rst @@ -516,7 +516,6 @@ Example:: +-----------------------------------------------+----------------------------------------------------------------+ - DATETIME -------- @@ -529,9 +528,9 @@ Argument type: DATETIME/STRING Return type map: -DATETIME, STRING -> DATETIME +(DATETIME, STRING) -> DATETIME -DATETIME -> DATETIME +(DATETIME) -> DATETIME Converting datetime with timezone to the second argument timezone. @@ -1308,21 +1307,26 @@ TIMESTAMP Description >>>>>>>>>>> -Usage: timestamp(expr) construct a timestamp type with the input string expr as an timestamp. If the argument is of date/datetime/timestamp type, cast expr to timestamp type with default timezone UTC. +Usage: timestamp(expr) constructs a timestamp type with the input string `expr` as an timestamp. If the argument is not a string, it casts `expr` to timestamp type with default timezone UTC. If argument is a time, it applies today's date before cast. +With two arguments `timestamp(expr1, expr2)` adds the time expression `expr2` to the date or datetime expression `expr1` and returns the result as a timestamp value. -Argument type: STRING/DATE/DATETIME/TIMESTAMP +Argument type: STRING/DATE/TIME/DATETIME/TIMESTAMP + +Return type map: + +(STRING/DATE/TIME/DATETIME/TIMESTAMP) -> TIMESTAMP -Return type: TIMESTAMP +(STRING/DATE/TIME/DATETIME/TIMESTAMP, STRING/DATE/TIME/DATETIME/TIMESTAMP) -> TIMESTAMP Example:: - >od source=people | eval `TIMESTAMP('2020-08-26 13:49:00')` = TIMESTAMP('2020-08-26 13:49:00') | fields `TIMESTAMP('2020-08-26 13:49:00')` + os> source=people | eval `TIMESTAMP('2020-08-26 13:49:00')` = TIMESTAMP('2020-08-26 13:49:00'), `TIMESTAMP('2020-08-26 13:49:00', TIME('12:15:42'))` = TIMESTAMP('2020-08-26 13:49:00', TIME('12:15:42')) | fields `TIMESTAMP('2020-08-26 13:49:00')`, `TIMESTAMP('2020-08-26 13:49:00', TIME('12:15:42'))` fetched rows / total rows = 1/1 - +------------------------------------+ - | TIMESTAMP('2020-08-26 13:49:00') | - |------------------------------------| - | TIMESTAMP '2020-08-26 13:49:00 | - +------------------------------------+ + +------------------------------------+------------------------------------------------------+ + | TIMESTAMP('2020-08-26 13:49:00') | TIMESTAMP('2020-08-26 13:49:00', TIME('12:15:42')) | + |------------------------------------+------------------------------------------------------| + | 2020-08-26 13:49:00 | 2020-08-27 02:04:42 | + +------------------------------------+------------------------------------------------------+ TO_DAYS