From 4f1fe884dc1321f3d38b230d67a37acfef067e9a Mon Sep 17 00:00:00 2001 From: Oswaldo Baptista Vicente Junior <45291656+oswaldobapvicjr@users.noreply.github.com> Date: Thu, 28 Mar 2024 00:18:03 -0300 Subject: [PATCH 1/6] Add functions DT_DATE_NOW and DT_DATE_TODAY --- .../config/ExpressionConfiguration.java | 2 + .../datetime/DateTimeNowFunction.java | 41 +++++++++++++++++ .../datetime/DateTimeTodayFunction.java | 44 +++++++++++++++++++ .../datetime/DateTimeFunctionsTest.java | 28 +++++++++++- 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/ezylang/evalex/functions/datetime/DateTimeNowFunction.java create mode 100644 src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java diff --git a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java index b7a86b61..78404125 100644 --- a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java +++ b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java @@ -188,6 +188,8 @@ public class ExpressionConfiguration { Map.entry("DT_DATE_NEW", new DateTimeNewFunction()), Map.entry("DT_DATE_PARSE", new DateTimeParseFunction()), Map.entry("DT_DATE_FORMAT", new DateTimeFormatFunction()), + Map.entry("DT_DATE_NOW", new DateTimeNowFunction()), + Map.entry("DT_DATE_TODAY", new DateTimeTodayFunction()), Map.entry("DT_DATE_TO_EPOCH", new DateTimeToEpochFunction()), Map.entry("DT_DURATION_NEW", new DurationNewFunction()), Map.entry("DT_DURATION_FROM_MILLIS", new DurationFromMillisFunction()), diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeNowFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeNowFunction.java new file mode 100644 index 00000000..bca7443b --- /dev/null +++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeNowFunction.java @@ -0,0 +1,41 @@ +/* + Copyright 2012-2024 Udo Klimaschewski + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package com.ezylang.evalex.functions.datetime; + +import java.time.Instant; + +import com.ezylang.evalex.Expression; +import com.ezylang.evalex.data.EvaluationValue; +import com.ezylang.evalex.functions.AbstractFunction; +import com.ezylang.evalex.parser.Token; + +/** + * Produces a new DATE_TIME that represents the current date and time. + *
+ * It is useful to calculate a value based on the current date and time. For example, if + * you know the start DATE_TIME of a running process, you might use the following + * expression to find the DURATION that represents the process age: + *
{@code DT_DATE_NOW() - startDateTime}+ * + * @author oswaldobapvicjr + */ +public class DateTimeNowFunction extends AbstractFunction { + @Override + public EvaluationValue evaluate( + Expression expression, Token functionToken, EvaluationValue... parameterValues) { + return expression.convertValue(Instant.now()); + } +} diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java new file mode 100644 index 00000000..c6fb5472 --- /dev/null +++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java @@ -0,0 +1,44 @@ +/* + Copyright 2012-2024 Udo Klimaschewski + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package com.ezylang.evalex.functions.datetime; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; + +import com.ezylang.evalex.Expression; +import com.ezylang.evalex.data.EvaluationValue; +import com.ezylang.evalex.functions.AbstractFunction; +import com.ezylang.evalex.parser.Token; + +/** + * Produces a new DATE_TIME that represents the current date, at midnight (00:00), in the + * system default time-zone. + *
+ * It is useful for DATE_TIME comparison, when the current time must not be considered. + * For example, in the expression: + *
{@code IF(expiryDate > DT_DATE_TODAY(), "expired", "valid")}+ * + * @author oswaldobapvicjr + */ +public class DateTimeTodayFunction extends AbstractFunction { + @Override + public EvaluationValue evaluate( + Expression expression, Token functionToken, EvaluationValue... parameterValues) { + Instant today = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant(); + return expression.convertValue(today); + } +} diff --git a/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java b/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java index cc465f58..caa45341 100644 --- a/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java +++ b/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java @@ -23,7 +23,12 @@ import com.ezylang.evalex.config.ExpressionConfiguration; import com.ezylang.evalex.config.TestConfigurationProvider; import com.ezylang.evalex.parser.ParseException; + +import java.time.Instant; +import java.time.LocalDate; import java.time.ZoneId; +import java.util.TimeZone; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -31,9 +36,17 @@ class DateTimeFunctionsTest extends BaseEvaluationTest { + private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("Europe/Berlin"); + + static { + // Let the default time-zone be set programmatically to standardize + // tests dependent on the default time-zone + TimeZone.setDefault(TimeZone.getTimeZone(DEFAULT_ZONE_ID)); + } + private static final ExpressionConfiguration DateTimeTestConfiguration = TestConfigurationProvider.StandardConfigurationWithAdditionalTestOperators.toBuilder() - .zoneId(ZoneId.of("Europe/Berlin")) + .zoneId(DEFAULT_ZONE_ID) .build(); @ParameterizedTest @@ -231,6 +244,19 @@ void testDateTimeToEpoch(String expression, String expectedResult) assertExpressionHasExpectedResult(expression, expectedResult); } + @Test + void testDateTimeNow() throws EvaluationException, ParseException { + assertExpressionHasExpectedResult( + "DT_DATE_NOW()", Instant.now().toString(), DateTimeTestConfiguration); + } + + @Test + void testDateTimeToday() throws EvaluationException, ParseException { + String expected = LocalDate.now().atStartOfDay(DEFAULT_ZONE_ID).toInstant().toString(); + assertExpressionHasExpectedResult( + "DT_DATE_TODAY()", expected, DateTimeTestConfiguration); + } + @ParameterizedTest @CsvSource( delimiter = '|', From cba74b124e073c84bda80b6fa16c52473f2bbcef Mon Sep 17 00:00:00 2001 From: Oswaldo Baptista Vicente Junior <45291656+oswaldobapvicjr@users.noreply.github.com> Date: Thu, 28 Mar 2024 00:23:41 -0300 Subject: [PATCH 2/6] Apply spotless --- .../datetime/DateTimeNowFunction.java | 18 ++++++++------ .../datetime/DateTimeTodayFunction.java | 24 +++++++++++-------- .../datetime/DateTimeFunctionsTest.java | 11 ++++----- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeNowFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeNowFunction.java index bca7443b..22392e0e 100644 --- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeNowFunction.java +++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeNowFunction.java @@ -15,20 +15,24 @@ */ package com.ezylang.evalex.functions.datetime; -import java.time.Instant; - import com.ezylang.evalex.Expression; import com.ezylang.evalex.data.EvaluationValue; import com.ezylang.evalex.functions.AbstractFunction; import com.ezylang.evalex.parser.Token; +import java.time.Instant; /** * Produces a new DATE_TIME that represents the current date and time. - *
- * It is useful to calculate a value based on the current date and time. For example, if - * you know the start DATE_TIME of a running process, you might use the following - * expression to find the DURATION that represents the process age: - *
{@code DT_DATE_NOW() - startDateTime}+ * + *
It is useful to calculate a value based on the current date and time. For example, if you know + * the start DATE_TIME of a running process, you might use the following expression to find the + * DURATION that represents the process age: + * + *
+ * + * {@code DT_DATE_NOW() - startDateTime} + * + ** * @author oswaldobapvicjr */ diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java index c6fb5472..52c0d7a5 100644 --- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java +++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java @@ -15,22 +15,26 @@ */ package com.ezylang.evalex.functions.datetime; -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; - import com.ezylang.evalex.Expression; import com.ezylang.evalex.data.EvaluationValue; import com.ezylang.evalex.functions.AbstractFunction; import com.ezylang.evalex.parser.Token; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; /** - * Produces a new DATE_TIME that represents the current date, at midnight (00:00), in the - * system default time-zone. - *
- * It is useful for DATE_TIME comparison, when the current time must not be considered. - * For example, in the expression: - *
{@code IF(expiryDate > DT_DATE_TODAY(), "expired", "valid")}+ * Produces a new DATE_TIME that represents the current date, at midnight (00:00), in the system + * default time-zone. + * + *
It is useful for DATE_TIME comparison, when the current time must not be considered. For + * example, in the expression: + * + *
+ * + * {@code IF(expiryDate > DT_DATE_TODAY(), "expired", "valid")} + * + ** * @author oswaldobapvicjr */ diff --git a/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java b/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java index caa45341..e79b0c87 100644 --- a/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java +++ b/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java @@ -23,12 +23,10 @@ import com.ezylang.evalex.config.ExpressionConfiguration; import com.ezylang.evalex.config.TestConfigurationProvider; import com.ezylang.evalex.parser.ParseException; - import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; import java.util.TimeZone; - import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -39,9 +37,9 @@ class DateTimeFunctionsTest extends BaseEvaluationTest { private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("Europe/Berlin"); static { - // Let the default time-zone be set programmatically to standardize - // tests dependent on the default time-zone - TimeZone.setDefault(TimeZone.getTimeZone(DEFAULT_ZONE_ID)); + // Let the default time-zone be set programmatically to standardize + // tests dependent on the default time-zone + TimeZone.setDefault(TimeZone.getTimeZone(DEFAULT_ZONE_ID)); } private static final ExpressionConfiguration DateTimeTestConfiguration = @@ -253,8 +251,7 @@ void testDateTimeNow() throws EvaluationException, ParseException { @Test void testDateTimeToday() throws EvaluationException, ParseException { String expected = LocalDate.now().atStartOfDay(DEFAULT_ZONE_ID).toInstant().toString(); - assertExpressionHasExpectedResult( - "DT_DATE_TODAY()", expected, DateTimeTestConfiguration); + assertExpressionHasExpectedResult("DT_DATE_TODAY()", expected, DateTimeTestConfiguration); } @ParameterizedTest From 725544ad6bf2d6362ab704a3113d31f7e88736da Mon Sep 17 00:00:00 2001 From: Oswaldo Baptista Vicente Junior <45291656+oswaldobapvicjr@users.noreply.github.com> Date: Thu, 28 Mar 2024 00:31:11 -0300 Subject: [PATCH 3/6] Update functions.md --- docs/references/functions.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/references/functions.md b/docs/references/functions.md index 406cd47b..bd41ecc9 100644 --- a/docs/references/functions.md +++ b/docs/references/functions.md @@ -86,6 +86,8 @@ Available through the _ExpressionConfiguration.StandardFunctionsDictionary_ cons | DT_DATE_NEW(millis) | Returns a new DATE_TIME from the epoch of 1970-01-01T00:00:00Z in milliseconds. | | DT_DATE_PARSE(value [,zoneId] [,format, ...]) | Converts the given string value to a date time value by using the optional time zone and formats. All formats are used until the first matching format. Without a format, the configured formats are used. Time zone can be NULL, the the configured time zone is used. | | DT_DATE_FORMAT(value, [,format] [,zoneId]) | Formats the given date-time to a string using the given optional format and time zone. Without a format, the first configured format is used. The zone id defaults to the configured zone id. | +| DT_DATE_NOW() | Produces a new DATE_TIME that represents the current date and time, in the system default time zo | +| DT_DATE_TODAY() | Produces a new DATE_TIME that represents the current date, at midnight (00:00), in the system default time zone. | | DT_DATE_TO_EPOCH(value) | Converts the given value to epoch timestamp in millisecond. | | DT_DURATION_NEW(days [,hours, minutes, seconds, nanos]) | Returns a new DURATION value with the given parameters. | | DT_DURATION_PARSE(value) | Converts the given ISO-8601 duration string representation to a duration value. E.g. "P2DT3H4M" parses 2 days, 3 hours and 4 minutes. | From aa39583a203101b69d6192e0e149ed0a63c11e26 Mon Sep 17 00:00:00 2001 From: Oswaldo Baptista Vicente Junior <45291656+oswaldobapvicjr@users.noreply.github.com> Date: Thu, 28 Mar 2024 00:57:46 -0300 Subject: [PATCH 4/6] Fix JUnit for DT_DATE_NOW --- .../functions/datetime/DateTimeFunctionsTest.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java b/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java index e79b0c87..93a3468b 100644 --- a/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java +++ b/src/test/java/com/ezylang/evalex/functions/datetime/DateTimeFunctionsTest.java @@ -23,7 +23,6 @@ import com.ezylang.evalex.config.ExpressionConfiguration; import com.ezylang.evalex.config.TestConfigurationProvider; import com.ezylang.evalex.parser.ParseException; -import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; import java.util.TimeZone; @@ -242,10 +241,16 @@ void testDateTimeToEpoch(String expression, String expectedResult) assertExpressionHasExpectedResult(expression, expectedResult); } - @Test - void testDateTimeNow() throws EvaluationException, ParseException { - assertExpressionHasExpectedResult( - "DT_DATE_NOW()", Instant.now().toString(), DateTimeTestConfiguration); + @ParameterizedTest + @CsvSource( + delimiter = '|', + value = { + "DT_DATE_NOW() > DT_DATE_TODAY() | true", + "DT_DATE_NOW() > (DT_DATE_TODAY() + DT_DURATION_PARSE(\"P1D\")) | false" + }) + void testDateTimeNow(String expression, String expectedResult) + throws EvaluationException, ParseException { + assertExpressionHasExpectedResult(expression, expectedResult); } @Test From d14e8cab5aac8f2532e799d00969cc097deb67b7 Mon Sep 17 00:00:00 2001 From: Oswaldo Baptista Vicente Junior <45291656+oswaldobapvicjr@users.noreply.github.com> Date: Fri, 29 Mar 2024 12:47:34 -0300 Subject: [PATCH 5/6] Fix doc --- docs/references/functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/references/functions.md b/docs/references/functions.md index bd41ecc9..c0d2a053 100644 --- a/docs/references/functions.md +++ b/docs/references/functions.md @@ -86,7 +86,7 @@ Available through the _ExpressionConfiguration.StandardFunctionsDictionary_ cons | DT_DATE_NEW(millis) | Returns a new DATE_TIME from the epoch of 1970-01-01T00:00:00Z in milliseconds. | | DT_DATE_PARSE(value [,zoneId] [,format, ...]) | Converts the given string value to a date time value by using the optional time zone and formats. All formats are used until the first matching format. Without a format, the configured formats are used. Time zone can be NULL, the the configured time zone is used. | | DT_DATE_FORMAT(value, [,format] [,zoneId]) | Formats the given date-time to a string using the given optional format and time zone. Without a format, the first configured format is used. The zone id defaults to the configured zone id. | -| DT_DATE_NOW() | Produces a new DATE_TIME that represents the current date and time, in the system default time zo | +| DT_DATE_NOW() | Produces a new DATE_TIME that represents the current date and time, in the system default time zone. | | DT_DATE_TODAY() | Produces a new DATE_TIME that represents the current date, at midnight (00:00), in the system default time zone. | | DT_DATE_TO_EPOCH(value) | Converts the given value to epoch timestamp in millisecond. | | DT_DURATION_NEW(days [,hours, minutes, seconds, nanos]) | Returns a new DURATION value with the given parameters. | From bc6c19096162bc7f5726fdf1c9d92334cd276d45 Mon Sep 17 00:00:00 2001 From: Oswaldo Baptista Vicente Junior <45291656+oswaldobapvicjr@users.noreply.github.com> Date: Mon, 1 Apr 2024 00:20:42 -0300 Subject: [PATCH 6/6] Fixing comments from 5th commit --- docs/references/functions.md | 6 +-- .../config/ExpressionConfiguration.java | 6 +-- .../ezylang/evalex/functions/FunctionIfc.java | 11 +++++ .../datetime/DateTimeFormatFunction.java | 1 + .../datetime/DateTimeParseFunction.java | 1 + .../datetime/DateTimeTodayFunction.java | 25 ++++++++++-- .../datetime/DurationNewFunction.java | 1 + .../evalex/parser/ShuntingYardConverter.java | 2 +- .../ezylang/evalex/BaseEvaluationTest.java | 5 +++ .../datetime/DateTimeFunctionsTest.java | 40 +++++++++---------- .../parser/ShuntingYardExceptionsTest.java | 3 +- 11 files changed, 69 insertions(+), 32 deletions(-) diff --git a/docs/references/functions.md b/docs/references/functions.md index c0d2a053..fade7160 100644 --- a/docs/references/functions.md +++ b/docs/references/functions.md @@ -82,14 +82,14 @@ Available through the _ExpressionConfiguration.StandardFunctionsDictionary_ cons | Name | Description | |--------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| DT_DATE_NEW(year, month, day [,hour, minute, second, millis, nanos] [,zoneId]) | Returns a new DATE_TIME value with the given parameters. Any optional time zone (string) can be specified, e.g. "Europe/Berlin", or "GMT+02:00. If no zone id is specified, the configured zone id is used. | +| DT_DATE_NEW(year, month, day [,hour, minute, second, millis, nanos] [,zoneId]) | Returns a new DATE_TIME value with the given parameters. Any optional time zone (string) can be specified, e.g. "Europe/Berlin", or "GMT+02:00". If no zone id is specified, the configured zone id is used. | | DT_DATE_NEW(millis) | Returns a new DATE_TIME from the epoch of 1970-01-01T00:00:00Z in milliseconds. | | DT_DATE_PARSE(value [,zoneId] [,format, ...]) | Converts the given string value to a date time value by using the optional time zone and formats. All formats are used until the first matching format. Without a format, the configured formats are used. Time zone can be NULL, the the configured time zone is used. | | DT_DATE_FORMAT(value, [,format] [,zoneId]) | Formats the given date-time to a string using the given optional format and time zone. Without a format, the first configured format is used. The zone id defaults to the configured zone id. | -| DT_DATE_NOW() | Produces a new DATE_TIME that represents the current date and time, in the system default time zone. | -| DT_DATE_TODAY() | Produces a new DATE_TIME that represents the current date, at midnight (00:00), in the system default time zone. | | DT_DATE_TO_EPOCH(value) | Converts the given value to epoch timestamp in millisecond. | | DT_DURATION_NEW(days [,hours, minutes, seconds, nanos]) | Returns a new DURATION value with the given parameters. | | DT_DURATION_PARSE(value) | Converts the given ISO-8601 duration string representation to a duration value. E.g. "P2DT3H4M" parses 2 days, 3 hours and 4 minutes. | | DT_DURATION_FROM_MILLIS(millis) | Returns a new DURATION value with the given milliseconds. | | DT_DURATION_TO_MILLIS(value) | Converts the given duration to a milliseconds value. | +| DT_DATE_NOW() | Produces a new DATE_TIME that represents the current date and time. | +| DT_DATE_TODAY([zoneId]) | Produces a new DATE_TIME that represents the current date, at midnight (00:00). An optional time zone (string) can be specified, e.g. "America/Sao_Paulo", or "GMT-03:00". If no zone id is specified, the configured zone id is used. | diff --git a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java index 78404125..923f77da 100644 --- a/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java +++ b/src/main/java/com/ezylang/evalex/config/ExpressionConfiguration.java @@ -188,13 +188,13 @@ public class ExpressionConfiguration { Map.entry("DT_DATE_NEW", new DateTimeNewFunction()), Map.entry("DT_DATE_PARSE", new DateTimeParseFunction()), Map.entry("DT_DATE_FORMAT", new DateTimeFormatFunction()), - Map.entry("DT_DATE_NOW", new DateTimeNowFunction()), - Map.entry("DT_DATE_TODAY", new DateTimeTodayFunction()), Map.entry("DT_DATE_TO_EPOCH", new DateTimeToEpochFunction()), Map.entry("DT_DURATION_NEW", new DurationNewFunction()), Map.entry("DT_DURATION_FROM_MILLIS", new DurationFromMillisFunction()), Map.entry("DT_DURATION_TO_MILLIS", new DurationToMillisFunction()), - Map.entry("DT_DURATION_PARSE", new DurationParseFunction())); + Map.entry("DT_DURATION_PARSE", new DurationParseFunction()), + Map.entry("DT_NOW", new DateTimeNowFunction()), + Map.entry("DT_TODAY", new DateTimeTodayFunction())); /** The math context to use. */ @Builder.Default @Getter private final MathContext mathContext = DEFAULT_MATH_CONTEXT; diff --git a/src/main/java/com/ezylang/evalex/functions/FunctionIfc.java b/src/main/java/com/ezylang/evalex/functions/FunctionIfc.java index beb63975..ee31efc9 100644 --- a/src/main/java/com/ezylang/evalex/functions/FunctionIfc.java +++ b/src/main/java/com/ezylang/evalex/functions/FunctionIfc.java @@ -79,4 +79,15 @@ default boolean isParameterLazy(int parameterIndex) { } return getFunctionParameterDefinitions().get(parameterIndex).isLazy(); } + + /** + * Returns the count of non-var-arg parameters defined by this function. If the function has + * var-args, the the result is the count of parameter definitions - 1. + * + * @return the count of non-var-arg parameters defined by this function. + */ + default int getCountOfNonVarArgParameters() { + int numOfParameters = getFunctionParameterDefinitions().size(); + return hasVarArgs() ? numOfParameters - 1 : numOfParameters; + } } diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFormatFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFormatFunction.java index 6cb7dfdb..908886e8 100644 --- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFormatFunction.java +++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeFormatFunction.java @@ -30,6 +30,7 @@ * format is given, the first format defined in the configured formats is used. Second optional * parameter is the zone-id to use wit formatting. Default is the configured zone-id. */ +@FunctionParameter(name = "value") @FunctionParameter(name = "parameters", isVarArg = true) public class DateTimeFormatFunction extends AbstractFunction { @Override diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeParseFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeParseFunction.java index fba7392a..d1a08de2 100644 --- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeParseFunction.java +++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeParseFunction.java @@ -36,6 +36,7 @@ * pattern will be used. If
NULL
is specified for the time zone, the currently
* configured zone is used. If no formatters a
*/
+@FunctionParameter(name = "value")
@FunctionParameter(name = "parameters", isVarArg = true)
public class DateTimeParseFunction extends AbstractFunction {
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java
index 52c0d7a5..97c4fb02 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DateTimeTodayFunction.java
@@ -15,17 +15,19 @@
*/
package com.ezylang.evalex.functions.datetime;
+import com.ezylang.evalex.EvaluationException;
import com.ezylang.evalex.Expression;
+import com.ezylang.evalex.config.ExpressionConfiguration;
import com.ezylang.evalex.data.EvaluationValue;
import com.ezylang.evalex.functions.AbstractFunction;
+import com.ezylang.evalex.functions.FunctionParameter;
import com.ezylang.evalex.parser.Token;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
/**
- * Produces a new DATE_TIME that represents the current date, at midnight (00:00), in the system
- * default time-zone.
+ * Produces a new DATE_TIME that represents the current date, at midnight (00:00).
*
* It is useful for DATE_TIME comparison, when the current time must not be considered. For * example, in the expression: @@ -36,13 +38,28 @@ * * * + *
This function may accept an optional time zone to be applied. If no zone ID is specified, the
+ * default zone ID defined at the {@link ExpressionConfiguration} will be used.
+ *
* @author oswaldobapvicjr
*/
+@FunctionParameter(name = "parameters", isVarArg = true)
public class DateTimeTodayFunction extends AbstractFunction {
@Override
public EvaluationValue evaluate(
- Expression expression, Token functionToken, EvaluationValue... parameterValues) {
- Instant today = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant();
+ Expression expression, Token functionToken, EvaluationValue... parameterValues)
+ throws EvaluationException {
+ ZoneId zoneId = parseZoneId(expression, functionToken, parameterValues);
+ Instant today = LocalDate.now().atStartOfDay(zoneId).toInstant();
return expression.convertValue(today);
}
+
+ private ZoneId parseZoneId(
+ Expression expression, Token functionToken, EvaluationValue... parameterValues)
+ throws EvaluationException {
+ if (parameterValues.length > 0 && !parameterValues[0].isNullValue()) {
+ return ZoneIdConverter.convert(functionToken, parameterValues[0].getStringValue());
+ }
+ return expression.getConfiguration().getZoneId();
+ }
}
diff --git a/src/main/java/com/ezylang/evalex/functions/datetime/DurationNewFunction.java b/src/main/java/com/ezylang/evalex/functions/datetime/DurationNewFunction.java
index 6cf184b0..62afd703 100644
--- a/src/main/java/com/ezylang/evalex/functions/datetime/DurationNewFunction.java
+++ b/src/main/java/com/ezylang/evalex/functions/datetime/DurationNewFunction.java
@@ -28,6 +28,7 @@
* All other parameters are optional and specify hours, minutes, seconds, milliseconds and
* nanoseconds.
*/
+@FunctionParameter(name = "days")
@FunctionParameter(name = "parameters", isVarArg = true)
public class DurationNewFunction extends AbstractFunction {
@Override
diff --git a/src/main/java/com/ezylang/evalex/parser/ShuntingYardConverter.java b/src/main/java/com/ezylang/evalex/parser/ShuntingYardConverter.java
index e4e53587..96e2544f 100644
--- a/src/main/java/com/ezylang/evalex/parser/ShuntingYardConverter.java
+++ b/src/main/java/com/ezylang/evalex/parser/ShuntingYardConverter.java
@@ -164,7 +164,7 @@ private void processBraceClose() throws ParseException {
private void validateFunctionParameters(Token functionToken, ArrayList