From 9316632891e37822cd4df9de22e6992d523938cb Mon Sep 17 00:00:00 2001 From: nikita-kladov Date: Wed, 1 Feb 2023 13:00:45 +0300 Subject: [PATCH] add interval functions --- .../function/BuiltinFunctionProvider.kt | 10 + .../evaluable/function/IntervalFunctions.kt | 189 ++++++++++++++++++ .../function_signatures_interval.json | 8 + .../functions_interval.json | 42 ++++ 4 files changed, 249 insertions(+) create mode 100644 client/android/div-evaluable/src/main/java/com/yandex/div/evaluable/function/IntervalFunctions.kt diff --git a/client/android/div-evaluable/src/main/java/com/yandex/div/evaluable/function/BuiltinFunctionProvider.kt b/client/android/div-evaluable/src/main/java/com/yandex/div/evaluable/function/BuiltinFunctionProvider.kt index a39a9a35b..2a9058113 100644 --- a/client/android/div-evaluable/src/main/java/com/yandex/div/evaluable/function/BuiltinFunctionProvider.kt +++ b/client/android/div-evaluable/src/main/java/com/yandex/div/evaluable/function/BuiltinFunctionProvider.kt @@ -93,6 +93,16 @@ object BuiltinFunctionProvider : FunctionProvider { registry.register(GetSeconds) registry.register(GetMillis) + // Interval functions + registry.register(GetIntervalTotalWeeks) + registry.register(GetIntervalTotalDays) + registry.register(GetIntervalTotalHours) + registry.register(GetIntervalHours) + registry.register(GetIntervalTotalMinutes) + registry.register(GetIntervalMinutes) + registry.register(GetIntervalTotalSeconds) + registry.register(GetIntervalSeconds) + // String functions registry.register(StringLength) registry.register(StringContains) diff --git a/client/android/div-evaluable/src/main/java/com/yandex/div/evaluable/function/IntervalFunctions.kt b/client/android/div-evaluable/src/main/java/com/yandex/div/evaluable/function/IntervalFunctions.kt new file mode 100644 index 000000000..519bfb6ff --- /dev/null +++ b/client/android/div-evaluable/src/main/java/com/yandex/div/evaluable/function/IntervalFunctions.kt @@ -0,0 +1,189 @@ +package com.yandex.div.evaluable.function + +import com.yandex.div.evaluable.EvaluableException +import com.yandex.div.evaluable.EvaluableType +import com.yandex.div.evaluable.Function +import com.yandex.div.evaluable.FunctionArgument + +private const val MILLIS_IN_SECONDS = 1000 +private const val SECONDS_IN_MINUTE = 60 +private const val MINUTES_IN_HOUR = 60 +private const val HOURS_IN_DAY = 24 +private const val DAYS_IN_WEEK = 7 + + +internal object GetIntervalSeconds : Function() { + + override val name = "getIntervalSeconds" + + override val declaredArgs = listOf( + FunctionArgument(type = EvaluableType.INTEGER) + ) + override val resultType = EvaluableType.INTEGER + override val isPure = true + + @Throws(EvaluableException::class) + override fun evaluate(args: List): Any { + val duration = args[0] as Int + + if (duration < 0) { + throw EvaluableException("Failed to evaluate [getIntervalSeconds(-1)]. Expecting non-negative number of milliseconds.") + } + + return duration / MILLIS_IN_SECONDS % SECONDS_IN_MINUTE + } +} + +internal object GetIntervalTotalSeconds : Function() { + + override val name = "getIntervalTotalSeconds" + + override val declaredArgs = listOf( + FunctionArgument(type = EvaluableType.INTEGER) + ) + override val resultType = EvaluableType.INTEGER + override val isPure = true + + @Throws(EvaluableException::class) + override fun evaluate(args: List): Any { + val duration = args[0] as Int + + if (duration < 0) { + throw EvaluableException("Failed to evaluate [getIntervalTotalSeconds(-1)]. Expecting non-negative number of milliseconds.") + } + + return duration / MILLIS_IN_SECONDS + } +} + +internal object GetIntervalMinutes : Function() { + + override val name = "getIntervalMinutes" + + override val declaredArgs = listOf( + FunctionArgument(type = EvaluableType.INTEGER) + ) + override val resultType = EvaluableType.INTEGER + override val isPure = true + + @Throws(EvaluableException::class) + override fun evaluate(args: List): Any { + val duration = args[0] as Int + + if (duration < 0) { + throw EvaluableException("Failed to evaluate [getIntervalMinutes(-1)]. Expecting non-negative number of milliseconds.") + } + + return duration / MILLIS_IN_SECONDS / SECONDS_IN_MINUTE % MINUTES_IN_HOUR + } +} + +internal object GetIntervalTotalMinutes : Function() { + + override val name = "getIntervalTotalMinutes" + + override val declaredArgs = listOf( + FunctionArgument(type = EvaluableType.INTEGER) + ) + override val resultType = EvaluableType.INTEGER + override val isPure = true + + @Throws(EvaluableException::class) + override fun evaluate(args: List): Any { + val duration = args[0] as Int + + if (duration < 0) { + throw EvaluableException("Failed to evaluate [getIntervalTotalMinutes(-1)]. Expecting non-negative number of milliseconds.") + } + + return duration / MILLIS_IN_SECONDS / SECONDS_IN_MINUTE + } +} + +internal object GetIntervalHours : Function() { + + override val name = "getIntervalHours" + + override val declaredArgs = listOf( + FunctionArgument(type = EvaluableType.INTEGER) + ) + override val resultType = EvaluableType.INTEGER + override val isPure = true + + @Throws(EvaluableException::class) + override fun evaluate(args: List): Any { + val duration = args[0] as Int + + if (duration < 0) { + throw EvaluableException("Failed to evaluate [getIntervalHours(-1)]. Expecting non-negative number of milliseconds.") + } + + return duration / MILLIS_IN_SECONDS / SECONDS_IN_MINUTE / MINUTES_IN_HOUR % HOURS_IN_DAY + } +} + +internal object GetIntervalTotalHours : Function() { + + override val name = "getIntervalTotalHours" + + override val declaredArgs = listOf( + FunctionArgument(type = EvaluableType.INTEGER) + ) + override val resultType = EvaluableType.INTEGER + override val isPure = true + + @Throws(EvaluableException::class) + override fun evaluate(args: List): Any { + val duration = args[0] as Int + + if (duration < 0) { + throw EvaluableException("Failed to evaluate [getIntervalTotalHours(-1)]. Expecting non-negative number of milliseconds.") + } + + return duration / MILLIS_IN_SECONDS / SECONDS_IN_MINUTE / MINUTES_IN_HOUR + } +} + +internal object GetIntervalTotalDays : Function() { + + override val name = "getIntervalTotalDays" + + override val declaredArgs = listOf( + FunctionArgument(type = EvaluableType.INTEGER) + ) + override val resultType = EvaluableType.INTEGER + override val isPure = true + + @Throws(EvaluableException::class) + override fun evaluate(args: List): Any { + val duration = args[0] as Int + + if (duration < 0) { + throw EvaluableException("Failed to evaluate [getIntervalTotalDays(-1)]. Expecting non-negative number of milliseconds.") + } + + return duration / MILLIS_IN_SECONDS / SECONDS_IN_MINUTE / MINUTES_IN_HOUR / HOURS_IN_DAY + } +} + +internal object GetIntervalTotalWeeks : Function() { + + override val name = "getIntervalTotalWeeks" + + override val declaredArgs = listOf( + FunctionArgument(type = EvaluableType.INTEGER) + ) + override val resultType = EvaluableType.INTEGER + override val isPure = true + + @Throws(EvaluableException::class) + override fun evaluate(args: List): Any { + val duration = args[0] as Int + + if (duration < 0) { + throw EvaluableException("Failed to evaluate [getIntervalTotalWeeks(-1)]. Expecting non-negative number of milliseconds.") + } + + return duration / MILLIS_IN_SECONDS / SECONDS_IN_MINUTE / MINUTES_IN_HOUR / HOURS_IN_DAY / DAYS_IN_WEEK + } +} diff --git a/test_data/expression_test_data/function_signatures_interval.json b/test_data/expression_test_data/function_signatures_interval.json index 8a704990c..77191cea2 100644 --- a/test_data/expression_test_data/function_signatures_interval.json +++ b/test_data/expression_test_data/function_signatures_interval.json @@ -12,6 +12,7 @@ ], "result_type": "integer", "platforms": [ + "android", "web", "ios" ] @@ -28,6 +29,7 @@ ], "result_type": "integer", "platforms": [ + "android", "web", "ios" ] @@ -44,6 +46,7 @@ ], "result_type": "integer", "platforms": [ + "android", "web", "ios" ] @@ -60,6 +63,7 @@ ], "result_type": "integer", "platforms": [ + "android", "web", "ios" ] @@ -76,6 +80,7 @@ ], "result_type": "integer", "platforms": [ + "android", "web", "ios" ] @@ -92,6 +97,7 @@ ], "result_type": "integer", "platforms": [ + "android", "web", "ios" ] @@ -108,6 +114,7 @@ ], "result_type": "integer", "platforms": [ + "android", "web", "ios" ] @@ -124,6 +131,7 @@ ], "result_type": "integer", "platforms": [ + "android", "web", "ios" ] diff --git a/test_data/expression_test_data/functions_interval.json b/test_data/expression_test_data/functions_interval.json index e543733c6..18b7d7705 100644 --- a/test_data/expression_test_data/functions_interval.json +++ b/test_data/expression_test_data/functions_interval.json @@ -8,6 +8,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -20,6 +21,7 @@ "value": "Failed to evaluate [getIntervalSeconds(-1)]. Expecting non-negative number of milliseconds." }, "platforms": [ + "android", "web", "ios" ] @@ -32,6 +34,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -44,6 +47,7 @@ "value": 1 }, "platforms": [ + "android", "web", "ios" ] @@ -56,6 +60,7 @@ "value": 10 }, "platforms": [ + "android", "web", "ios" ] @@ -68,6 +73,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -80,6 +86,7 @@ "value": "Failed to evaluate [getIntervalTotalSeconds(-1)]. Expecting non-negative number of milliseconds." }, "platforms": [ + "android", "web", "ios" ] @@ -92,6 +99,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -104,6 +112,7 @@ "value": 1 }, "platforms": [ + "android", "web", "ios" ] @@ -116,6 +125,7 @@ "value": 196330 }, "platforms": [ + "android", "web", "ios" ] @@ -128,6 +138,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -140,6 +151,7 @@ "value": "Failed to evaluate [getIntervalMinutes(-1)]. Expecting non-negative number of milliseconds." }, "platforms": [ + "android", "web", "ios" ] @@ -152,6 +164,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -164,6 +177,7 @@ "value": 1 }, "platforms": [ + "android", "web", "ios" ] @@ -176,6 +190,7 @@ "value": 32 }, "platforms": [ + "android", "web", "ios" ] @@ -188,6 +203,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -200,6 +216,7 @@ "value": "Failed to evaluate [getIntervalTotalMinutes(-1)]. Expecting non-negative number of milliseconds." }, "platforms": [ + "android", "web", "ios" ] @@ -212,6 +229,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -224,6 +242,7 @@ "value": 1 }, "platforms": [ + "android", "web", "ios" ] @@ -236,6 +255,7 @@ "value": 3272 }, "platforms": [ + "android", "web", "ios" ] @@ -248,6 +268,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -260,6 +281,7 @@ "value": "Failed to evaluate [getIntervalHours(-1)]. Expecting non-negative number of milliseconds." }, "platforms": [ + "android", "web", "ios" ] @@ -272,6 +294,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -284,6 +307,7 @@ "value": 1 }, "platforms": [ + "android", "web", "ios" ] @@ -296,6 +320,7 @@ "value": 6 }, "platforms": [ + "android", "web", "ios" ] @@ -308,6 +333,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -320,6 +346,7 @@ "value": "Failed to evaluate [getIntervalTotalHours(-1)]. Expecting non-negative number of milliseconds." }, "platforms": [ + "android", "web", "ios" ] @@ -332,6 +359,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -344,6 +372,7 @@ "value": 1 }, "platforms": [ + "android", "web", "ios" ] @@ -356,6 +385,7 @@ "value": 54 }, "platforms": [ + "android", "web", "ios" ] @@ -368,6 +398,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -380,6 +411,7 @@ "value": "Failed to evaluate [getIntervalTotalDays(-1)]. Expecting non-negative number of milliseconds." }, "platforms": [ + "android", "web", "ios" ] @@ -392,6 +424,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -404,6 +437,7 @@ "value": 1 }, "platforms": [ + "android", "web", "ios" ] @@ -416,6 +450,7 @@ "value": 2 }, "platforms": [ + "android", "web", "ios" ] @@ -428,6 +463,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -440,6 +476,7 @@ "value": "Failed to evaluate [getIntervalTotalWeeks(-1)]. Expecting non-negative number of milliseconds." }, "platforms": [ + "android", "web", "ios" ] @@ -452,6 +489,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -464,6 +502,7 @@ "value": 1 }, "platforms": [ + "android", "web", "ios" ] @@ -476,6 +515,7 @@ "value": 0 }, "platforms": [ + "android", "web", "ios" ] @@ -488,6 +528,7 @@ "value": 2 }, "platforms": [ + "android", "web", "ios" ] @@ -500,6 +541,7 @@ "value": "10:50:10" }, "platforms": [ + "android", "web", "ios" ]