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 fc425c6c20..26a15c0ee4 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -768,6 +768,22 @@ public static FunctionExpression current_date(FunctionProperties functionPropert return compile(functionProperties, BuiltinFunctionName.CURRENT_DATE, args); } + public static FunctionExpression utc_date(FunctionProperties functionProperties, + Expression... args) { + return compile(functionProperties, BuiltinFunctionName.UTC_DATE, args); + } + + public static FunctionExpression utc_time(FunctionProperties functionProperties, + Expression... args) { + return compile(functionProperties, BuiltinFunctionName.UTC_TIME, args); + } + + public static FunctionExpression utc_timestamp(FunctionProperties functionProperties, + Expression... args) { + return compile(functionProperties, BuiltinFunctionName.UTC_TIMESTAMP, args); + + } + @SuppressWarnings("unchecked") private static T compile(FunctionProperties functionProperties, 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 a111f672af..ed8063d8ff 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 @@ -63,6 +63,7 @@ import org.opensearch.sql.expression.function.DefaultFunctionResolver; import org.opensearch.sql.expression.function.FunctionDSL; import org.opensearch.sql.expression.function.FunctionName; +import org.opensearch.sql.expression.function.FunctionProperties; import org.opensearch.sql.expression.function.FunctionResolver; import org.opensearch.sql.utils.DateTimeUtils; @@ -126,6 +127,9 @@ public void register(BuiltinFunctionRepository repository) { repository.register(time()); repository.register(time_to_sec()); repository.register(timestamp()); + repository.register(utc_date()); + repository.register(utc_time()); + repository.register(utc_timestamp()); repository.register(date_format()); repository.register(to_days()); repository.register(unix_timestamp()); @@ -566,6 +570,33 @@ private FunctionResolver unix_timestamp() { ); } + /** + * UTC_DATE(). return the current UTC Date in format yyyy-MM-dd + */ + private DefaultFunctionResolver utc_date() { + return define(BuiltinFunctionName.UTC_DATE.getName(), + implWithProperties(functionProperties + -> exprUtcDate(functionProperties), DATE)); + } + + /** + * UTC_TIME(). return the current UTC Time in format HH:mm:ss + */ + private DefaultFunctionResolver utc_time() { + return define(BuiltinFunctionName.UTC_TIME.getName(), + implWithProperties(functionProperties + -> exprUtcTime(functionProperties), TIME)); + } + + /** + * UTC_TIMESTAMP(). return the current UTC TimeStamp in format yyyy-MM-dd HH:mm:ss + */ + private DefaultFunctionResolver utc_timestamp() { + return define(BuiltinFunctionName.UTC_TIMESTAMP.getName(), + implWithProperties(functionProperties + -> exprUtcTimeStamp(functionProperties), DATETIME)); + } + /** * WEEK(DATE[,mode]). return the week number for date. */ @@ -1063,6 +1094,38 @@ private ExprValue exprTimeToSec(ExprValue time) { return new ExprLongValue(time.timeValue().toSecondOfDay()); } + /** + * UTC_DATE implementation for ExprValue. + * + * @param functionProperties FunctionProperties. + * @return ExprValue. + */ + private ExprValue exprUtcDate(FunctionProperties functionProperties) { + return new ExprDateValue(exprUtcTimeStamp(functionProperties).dateValue()); + } + + /** + * UTC_TIME implementation for ExprValue. + * + * @param functionProperties FunctionProperties. + * @return ExprValue. + */ + private ExprValue exprUtcTime(FunctionProperties functionProperties) { + return new ExprTimeValue(exprUtcTimeStamp(functionProperties).timeValue()); + } + + /** + * UTC_TIMESTAMP implementation for ExprValue. + * + * @param functionProperties FunctionProperties. + * @return ExprValue. + */ + private ExprValue exprUtcTimeStamp(FunctionProperties functionProperties) { + var zdt = ZonedDateTime.now(functionProperties.getQueryStartClock()) + .withZoneSameInstant(ZoneId.of("UTC")); + return new ExprDatetimeValue(zdt.toLocalDateTime()); + } + /** * To_days implementation for ExprValue. * diff --git a/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java b/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java index b23c7613d6..28d423676b 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java @@ -90,6 +90,9 @@ public enum BuiltinFunctionName { TIMESTAMP(FunctionName.of("timestamp")), DATE_FORMAT(FunctionName.of("date_format")), TO_DAYS(FunctionName.of("to_days")), + UTC_DATE(FunctionName.of("utc_date")), + UTC_TIME(FunctionName.of("utc_time")), + UTC_TIMESTAMP(FunctionName.of("utc_timestamp")), UNIX_TIMESTAMP(FunctionName.of("unix_timestamp")), WEEK(FunctionName.of("week")), WEEK_OF_YEAR(FunctionName.of("week_of_year")), diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/NowLikeFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/NowLikeFunctionTest.java index 6f7548b5cb..4b8a4aac5e 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/NowLikeFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/NowLikeFunctionTest.java @@ -19,10 +19,13 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Period; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; import java.time.temporal.TemporalUnit; import java.util.List; +import java.util.TimeZone; import java.util.concurrent.Callable; import java.util.function.BiFunction; import java.util.function.Function; @@ -103,6 +106,31 @@ void current_date() { () -> LocalDate.now(functionProperties.getQueryStartClock())); } + @Test + void utc_date() { + test_now_like_functions(DSL::utc_date, DATE, false, + () -> utcDateTimeNow(functionProperties).toLocalDate()); + } + + @Test + void utc_time() { + test_now_like_functions(DSL::utc_time, TIME, false, + () -> utcDateTimeNow(functionProperties).toLocalTime()); + } + + @Test + void utc_timestamp() { + test_now_like_functions(DSL::utc_timestamp, DATETIME, false, + () -> utcDateTimeNow(functionProperties)); + } + + private static LocalDateTime utcDateTimeNow(FunctionProperties functionProperties) { + ZonedDateTime zonedDateTime = + LocalDateTime.now(functionProperties.getQueryStartClock()) + .atZone(TimeZone.getDefault().toZoneId()); + return zonedDateTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); + } + /** * Check how NOW-like functions are processed. * diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index 843d6c7e45..733a555c81 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -2119,6 +2119,74 @@ Examples:: +----------------------------------------------------+ +UTC_DATE +-------- + +Description +>>>>>>>>>>> + +Returns the current UTC date as a value in 'YYYY-MM-DD'. + +Return type: DATE + +Specification: UTC_DATE() -> DATE + +Example:: + + > SELECT UTC_DATE(); + fetched rows / total rows = 1/1 + +--------------+ + | utc_date() | + |--------------| + | 2022-10-03 | + +--------------+ + + +UTC_TIME +-------- + +Description +>>>>>>>>>>> + +Returns the current UTC time as a value in 'hh:mm:ss'. + +Return type: TIME + +Specification: UTC_TIME() -> TIME + +Example:: + + > SELECT UTC_TIME(); + fetched rows / total rows = 1/1 + +--------------+ + | utc_time() | + |--------------| + | 17:54:27 | + +--------------+ + + +UTC_TIMESTAMP +------------- + +Description +>>>>>>>>>>> + +Returns the current UTC timestamp as a value in 'YYYY-MM-DD hh:mm:ss'. + +Return type: DATETIME + +Specification: UTC_TIMESTAMP() -> DATETIME + +Example:: + + > SELECT UTC_TIMESTAMP(); + fetched rows / total rows = 1/1 + +---------------------+ + | utc_timestamp() | + |---------------------| + | 2022-10-03 17:54:28 | + +---------------------+ + WEEK ---- diff --git a/docs/user/ppl/functions/datetime.rst b/docs/user/ppl/functions/datetime.rst index ca191e2426..99ccc8e360 100644 --- a/docs/user/ppl/functions/datetime.rst +++ b/docs/user/ppl/functions/datetime.rst @@ -1251,6 +1251,75 @@ Example:: +--------------------------+-----------------------------+ +UTC_DATE +-------- + +Description +>>>>>>>>>>> + +Returns the current UTC date as a value in 'YYYY-MM-DD'. + +Return type: DATE + +Specification: UTC_DATE() -> DATE + +Example:: + + > source=people | eval `UTC_DATE()` = UTC_DATE() | fields `UTC_DATE()` + fetched rows / total rows = 1/1 + +--------------+ + | UTC_DATE() | + |--------------| + | 2022-10-03 | + +--------------+ + + +UTC_TIME +-------- + +Description +>>>>>>>>>>> + +Returns the current UTC time as a value in 'hh:mm:ss'. + +Return type: TIME + +Specification: UTC_TIME() -> TIME + +Example:: + + > source=people | eval `UTC_TIME()` = UTC_TIME() | fields `UTC_TIME()` + fetched rows / total rows = 1/1 + +--------------+ + | UTC_TIME() | + |--------------| + | 17:54:27 | + +--------------+ + + +UTC_TIMESTAMP +------------- + +Description +>>>>>>>>>>> + +Returns the current UTC timestamp as a value in 'YYYY-MM-DD hh:mm:ss'. + +Return type: DATETIME + +Specification: UTC_TIMESTAMP() -> DATETIME + +Example:: + + > source=people | eval `UTC_TIMESTAMP()` = UTC_TIMESTAMP() | fields `UTC_TIMESTAMP()` + fetched rows / total rows = 1/1 + +---------------------+ + | UTC_TIMESTAMP() | + |---------------------| + | 2022-10-03 17:54:28 | + +---------------------+ + + WEEK ---- diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeFunctionIT.java index afabc241fe..004d8a0648 100644 --- a/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/ppl/DateTimeFunctionIT.java @@ -6,8 +6,11 @@ package org.opensearch.sql.ppl; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATE; import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_PEOPLE2; +import static org.opensearch.sql.sql.DateTimeFunctionIT.utcDateTimeNow; import static org.opensearch.sql.util.MatcherUtils.rows; import static org.opensearch.sql.util.MatcherUtils.schema; import static org.opensearch.sql.util.MatcherUtils.verifySchema; @@ -754,6 +757,33 @@ private List> nowLikeFunctionsData() { .put("referenceGetter", (Supplier) LocalDate::now) .put("parser", (BiFunction) LocalDate::parse) .put("serializationPattern", "uuuu-MM-dd") + .build(), + ImmutableMap.builder() + .put("name", "utc_date") + .put("hasFsp", false) + .put("hasShortcut", false) + .put("constValue", true) + .put("referenceGetter", (Supplier) ()-> utcDateTimeNow().toLocalDate()) + .put("parser", (BiFunction) LocalDate::parse) + .put("serializationPattern", "uuuu-MM-dd") + .build(), + ImmutableMap.builder() + .put("name", "utc_time") + .put("hasFsp", false) + .put("hasShortcut", false) + .put("constValue", true) + .put("referenceGetter", (Supplier) ()-> utcDateTimeNow().toLocalTime()) + .put("parser", (BiFunction) LocalTime::parse) + .put("serializationPattern", "HH:mm:ss") + .build(), + ImmutableMap.builder() + .put("name", "utc_timestamp") + .put("hasFsp", false) + .put("hasShortcut", false) + .put("constValue", true) + .put("referenceGetter", (Supplier) ()-> utcDateTimeNow()) + .put("parser", (BiFunction) LocalDateTime::parse) + .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") .build() ); } diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java index 3503877d64..f60bd1efb0 100644 --- a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java @@ -24,6 +24,8 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Period; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; @@ -640,6 +642,12 @@ public void testMakeDate() throws IOException { verifyDataRows(result, rows("1945-01-06", "1989-06-06")); } + public static LocalDateTime utcDateTimeNow() { + ZonedDateTime zonedDateTime = + LocalDateTime.now().atZone(TimeZone.getDefault().toZoneId()); + return zonedDateTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); + } + private List> nowLikeFunctionsData() { return List.of( ImmutableMap.builder() @@ -722,6 +730,33 @@ private List> nowLikeFunctionsData() { .put("referenceGetter", (Supplier) LocalDate::now) .put("parser", (BiFunction) LocalDate::parse) .put("serializationPattern", "uuuu-MM-dd") + .build(), + ImmutableMap.builder() + .put("name", "utc_date") + .put("hasFsp", false) + .put("hasShortcut", false) + .put("constValue", true) + .put("referenceGetter", (Supplier) (()-> utcDateTimeNow().toLocalDate())) + .put("parser", (BiFunction) LocalDate::parse) + .put("serializationPattern", "uuuu-MM-dd") + .build(), + ImmutableMap.builder() + .put("name", "utc_time") + .put("hasFsp", false) + .put("hasShortcut", false) + .put("constValue", true) + .put("referenceGetter", (Supplier) (()-> utcDateTimeNow().toLocalTime())) + .put("parser", (BiFunction) LocalTime::parse) + .put("serializationPattern", "HH:mm:ss") + .build(), + ImmutableMap.builder() + .put("name", "utc_timestamp") + .put("hasFsp", false) + .put("hasShortcut", false) + .put("constValue", true) + .put("referenceGetter", (Supplier) DateTimeFunctionIT::utcDateTimeNow) + .put("parser", (BiFunction) LocalDateTime::parse) + .put("serializationPattern", "uuuu-MM-dd HH:mm:ss") .build() ); } diff --git a/ppl/src/test/java/org/opensearch/sql/ppl/antlr/NowLikeFunctionParserTest.java b/ppl/src/test/java/org/opensearch/sql/ppl/antlr/NowLikeFunctionParserTest.java index dda404f29a..fb849f6de7 100644 --- a/ppl/src/test/java/org/opensearch/sql/ppl/antlr/NowLikeFunctionParserTest.java +++ b/ppl/src/test/java/org/opensearch/sql/ppl/antlr/NowLikeFunctionParserTest.java @@ -46,7 +46,10 @@ public static Iterable functionNames() { {"curtime", true, false}, {"current_time", true, true}, {"curdate", false, false}, - {"current_date", false, true} + {"current_date", false, true}, + {"utc_date", false, false}, + {"utc_time", false, false}, + {"utc_timestamp", false, false} }); } diff --git a/ppl/src/test/java/org/opensearch/sql/ppl/parser/AstNowLikeFunctionTest.java b/ppl/src/test/java/org/opensearch/sql/ppl/parser/AstNowLikeFunctionTest.java index 711e780f3b..ddcde513dd 100644 --- a/ppl/src/test/java/org/opensearch/sql/ppl/parser/AstNowLikeFunctionTest.java +++ b/ppl/src/test/java/org/opensearch/sql/ppl/parser/AstNowLikeFunctionTest.java @@ -56,7 +56,10 @@ public static Iterable functionNames() { {"curtime", false, false}, {"current_time", false, false}, {"curdate", false, false}, - {"current_date", false, false} + {"current_date", false, false}, + {"utc_date", false, false}, + {"utc_time", false, false}, + {"utc_timestamp", false, false} }); } diff --git a/sql/src/main/antlr/OpenSearchSQLLexer.g4 b/sql/src/main/antlr/OpenSearchSQLLexer.g4 index a359f48be3..01016992e9 100644 --- a/sql/src/main/antlr/OpenSearchSQLLexer.g4 +++ b/sql/src/main/antlr/OpenSearchSQLLexer.g4 @@ -258,9 +258,9 @@ TIME_TO_SEC: 'TIME_TO_SEC'; TIMESTAMP: 'TIMESTAMP'; TRUNCATE: 'TRUNCATE'; TO_DAYS: 'TO_DAYS'; -UTC_DATE: 'UTC_DATE'; UNIX_TIMESTAMP: 'UNIX_TIMESTAMP'; UPPER: 'UPPER'; +UTC_DATE: 'UTC_DATE'; UTC_TIME: 'UTC_TIME'; UTC_TIMESTAMP: 'UTC_TIMESTAMP'; diff --git a/sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java b/sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java index bfd0f93ec9..778a62ebd8 100644 --- a/sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java +++ b/sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java @@ -167,7 +167,10 @@ private static Stream nowLikeFunctionsData() { Arguments.of("curtime", true, false), Arguments.of("current_time", true, true), Arguments.of("curdate", false, false), - Arguments.of("current_date", false, true) + Arguments.of("current_date", false, true), + Arguments.of("utc_date", false, true), + Arguments.of("utc_time", false, true), + Arguments.of("utc_timestamp", false, true) ); } diff --git a/sql/src/test/java/org/opensearch/sql/sql/parser/AstNowLikeFunctionTest.java b/sql/src/test/java/org/opensearch/sql/sql/parser/AstNowLikeFunctionTest.java index 19b48ca0bd..4ce2a2d3f7 100644 --- a/sql/src/test/java/org/opensearch/sql/sql/parser/AstNowLikeFunctionTest.java +++ b/sql/src/test/java/org/opensearch/sql/sql/parser/AstNowLikeFunctionTest.java @@ -32,8 +32,11 @@ private static Stream allFunctions() { "curtime", "localtimestamp", "localtime", - "now", - "sysdate") + "now", + "sysdate", + "utc_date", + "utc_time", + "utc_timestamp") .map(Arguments::of); }