diff --git a/docs/develop/feel-built-in-functions.md b/docs/develop/feel-built-in-functions.md index b69959ec5..72600651c 100644 --- a/docs/develop/feel-built-in-functions.md +++ b/docs/develop/feel-built-in-functions.md @@ -826,3 +826,55 @@ Returns the current date. today() // date("2020-07-31") ``` + +### day of week() + +Returns the day of the week according to the Gregorian calendar. Note that it returns always the english name of the day. + +* parameters: + * `date`: date/date-time +* result: string + +```js +day of week(date("2019-09-17")) +// "Tuesday" +``` + +### day of year() + +Returns the Gregorian number of the day within the year. + +* parameters: + * `date`: date/date-time +* result: number + +```js +day of year(date("2019-09-17")) +// 260 +``` + +### week of year() + +Returns the Gregorian number of the week within the year, according to ISO 8601. + +* parameters: + * `date`: date/date-time +* result: number + +```js +week of year(date("2019-09-17")) +// 38 +``` + +### month of year() + +Returns the month of the week according to the Gregorian calendar. Note that it returns always the english name of the month. + +* parameters: + * `date`: date/date-time +* result: string + +```js +month of year(date("2019-09-17")) +// "September" +``` diff --git a/src/main/scala/org/camunda/feel/impl/builtin/TemporalBuiltinFunctions.scala b/src/main/scala/org/camunda/feel/impl/builtin/TemporalBuiltinFunctions.scala index 8acb6e33d..ca0b74bf2 100644 --- a/src/main/scala/org/camunda/feel/impl/builtin/TemporalBuiltinFunctions.scala +++ b/src/main/scala/org/camunda/feel/impl/builtin/TemporalBuiltinFunctions.scala @@ -1,14 +1,22 @@ package org.camunda.feel.impl.builtin -import org.camunda.feel.FeelEngineClock +import java.time.format.TextStyle +import java.time.temporal.WeekFields +import java.util.Locale + import org.camunda.feel.impl.builtin.BuiltinFunction.builtinFunction -import org.camunda.feel.syntaxtree.{ValDate, ValDateTime} +import org.camunda.feel.syntaxtree._ +import org.camunda.feel.{Date, FeelEngineClock} class TemporalBuiltinFunctions(clock: FeelEngineClock) { def functions = Map( "now" -> List(nowFunction), - "today" -> List(todayFunction) + "today" -> List(todayFunction), + "day of year" -> List(dateTimeFunction(getDayOfYear)), + "day of week" -> List(dateTimeFunction(getDayOfWeek)), + "month of year" -> List(dateTimeFunction(getMonthOfYear)), + "week of year" -> List(dateTimeFunction(getWeekOfYear)) ) private def nowFunction = builtinFunction( @@ -29,4 +37,37 @@ class TemporalBuiltinFunctions(clock: FeelEngineClock) { } ) + private def dateTimeFunction(function: Date => Val): ValFunction = + builtinFunction( + params = List("date"), + invoke = { + case List(ValDate(date)) => function(date) + case List(ValDateTime(date)) => function(date.toLocalDate) + case List(ValLocalDateTime(date)) => function(date.toLocalDate) + } + ) + + private def getDayOfYear(date: Date): ValNumber = { + val dayOfYear = date.getDayOfYear + ValNumber(dayOfYear) + } + + private def getDayOfWeek(date: Date): ValString = { + val dayOfWeek = date.getDayOfWeek + val displayName = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.ENGLISH) + ValString(displayName) + } + + private def getMonthOfYear(date: Date): ValString = { + val month = date.getMonth + val displayName = month.getDisplayName(TextStyle.FULL, Locale.ENGLISH) + ValString(displayName) + } + + private def getWeekOfYear(date: Date): ValNumber = { + val temporalField = WeekFields.ISO.weekOfWeekBasedYear() + val weekOfYear = date.get(temporalField) + ValNumber(weekOfYear) + } + } diff --git a/src/main/scala/org/camunda/feel/impl/parser/FeelParser.scala b/src/main/scala/org/camunda/feel/impl/parser/FeelParser.scala index 8dd98aab0..7cf1da7df 100644 --- a/src/main/scala/org/camunda/feel/impl/parser/FeelParser.scala +++ b/src/main/scala/org/camunda/feel/impl/parser/FeelParser.scala @@ -66,7 +66,11 @@ object FeelParser extends JavaTokenParsers { | "distinct values" | "get entries" | "get value" - | "is defined") + | "is defined" + | "day of year" + | "day of week" + | "month of year" + | "week of year") // list of built-in function parameter names with whitespaces // -- other names match the 'parameter name' pattern diff --git a/src/test/scala/org/camunda/feel/impl/builtin/BuiltinTemporalFunctionsTest.scala b/src/test/scala/org/camunda/feel/impl/builtin/BuiltinTemporalFunctionsTest.scala index ed99f444b..d88e28f5e 100644 --- a/src/test/scala/org/camunda/feel/impl/builtin/BuiltinTemporalFunctionsTest.scala +++ b/src/test/scala/org/camunda/feel/impl/builtin/BuiltinTemporalFunctionsTest.scala @@ -19,7 +19,7 @@ package org.camunda.feel.impl.builtin import java.time.{LocalDate, LocalTime, ZoneId, ZonedDateTime} import org.camunda.feel.impl.FeelIntegrationTest -import org.camunda.feel.syntaxtree.{ValDate, ValDateTime} +import org.camunda.feel.syntaxtree.{ValDate, ValDateTime, ValNumber, ValString} import org.scalatest.{BeforeAndAfter, FlatSpec, Matchers} class BuiltinTemporalFunctionsTest @@ -34,6 +34,11 @@ class BuiltinTemporalFunctionsTest ZoneId.of("Europe/Berlin") ) + private val date = "date(2019,9,17)" + private val localDateTime = """date and time("2019-09-17T14:30:00")""" + private val dateTime = + """date and time("2019-09-17T14:30:00@Europe/Berlin")""" + "The now() function" should "return the current date-time" in withClock { clock => clock.currentTime(now) @@ -46,4 +51,41 @@ class BuiltinTemporalFunctionsTest eval(""" today() """) should be(ValDate(now.toLocalDate)) } + "The day of year() function" should "return the day within the year" in { + + eval(s"day of year($date)") should be(ValNumber(260)) + eval(s"day of year($localDateTime) ") should be(ValNumber(260)) + eval(s"day of year($dateTime) ") should be(ValNumber(260)) + + eval(s""" day of year(date("2019-12-31")) """) should be(ValNumber(365)) + eval(s""" day of year(date("2020-12-31")) """) should be(ValNumber(366)) + } + + "The day of week() function" should "return the day of the week" in { + + eval(s"day of week($date)") should be(ValString("Tuesday")) + eval(s"day of week($localDateTime)") should be(ValString("Tuesday")) + eval(s"day of week($dateTime)") should be(ValString("Tuesday")) + } + + "The month of year() function" should "return the month of the year" in { + + eval(s"month of year($date)") should be(ValString("September")) + eval(s"month of year($localDateTime)") should be(ValString("September")) + eval(s"month of year($dateTime)") should be(ValString("September")) + } + + "The week of year() function" should "return the number of week within the year" in { + + eval(s"week of year($date)") should be(ValNumber(38)) + eval(s"week of year($localDateTime)") should be(ValNumber(38)) + eval(s"week of year($dateTime)") should be(ValNumber(38)) + + eval(""" week of year(date(2003,12,29)) """) should be(ValNumber(1)) + eval(""" week of year(date(2004,1,4)) """) should be(ValNumber(1)) + eval(""" week of year(date(2005,1,1)) """) should be(ValNumber(53)) + eval(""" week of year(date(2005,1,3)) """) should be(ValNumber(1)) + eval(""" week of year(date(2005,1,9)) """) should be(ValNumber(1)) + } + }