FEEL

What changed in DMN 1.6, 1.5, 1.4 and 1.3

DMN has grown since 1.3: temporal reasoning, a stream of new built-in functions, generalized unary tests, and with 1.6 a second dialect of the expression language. This page collects what changed in each version, with the FEEL-visible parts backed by expressions this site's interpreter evaluated at build time.

Jump to: DMN 1.6 Beta 1 · DMN 1.5 · DMN 1.4 · DMN 1.3

DMN 1.6 Beta 1 · September 2024

The largest expression-language release since 1.3. B-FEEL adds a second dialect with error-tolerant semantics, the descendant operator makes nested lookups possible, and several built-ins gain shorter forms.

B-FEEL, the business-friendly dialect

A second dialect sharing FEEL's grammar but not its error semantics. Standard FEEL propagates null through type errors, so one bad input collapses a whole decision; B-FEEL substitutes type defaults,0 for numbers, the empty string, false, the empty list, the epoch for dates, and coerces mixed-type arithmetic. In B-FEEL null means missing data and nothing else.

"a" = 1
FEEL: nullB-FEEL: false Try it ↑
"total " + null
FEEL: nullB-FEEL: total Try it ↑
date("2024-06-31")
FEEL: nullB-FEEL: 1970-01-01 Try it ↑

Descendant operator ...

Recursively collects every value reachable under a name, at any depth, instead of requiring an exact path. Useful against deeply nested or irregularly shaped input data.

{a: {b: {b: 1}}}...b
[{b=1}, 1] Try it ↑

number(x) with a single argument

Parses a string into a number without the grouping and decimal separator arguments the three-parameter form requires.

number("1.5")

date and time(date, time, timezone)

Builds a date and time from separate components with an explicit zone, given either as an offset or as an IANA identifier. It replaces the time literal with an appended zone, which 1.6 deprecates.

date and time(date("2026-07-01"), time("10:00:00"), "Europe/Zurich")
2026-07-01T10:00@Europe/Zurich Try it ↑

Rounding functions with a single argument

round up, round down, round half up and round half down may be called without a scale, which then defaults to 0.

round up(1.5)
round down(1.7)
round half up(2.5)

Deprecation: time literals with an appended zone

The form time("HH:mm:ss@Zone") is deprecated in favour of the three-argument date and time. Existing expressions keep working.

time("10:00:00@Europe/Zurich")
10:00:00@Europe/Zurich Try it ↑

.value on temporal types

date, date and time and both duration types gain a .value property returning their numeric representation: seconds since the epoch for the date types, a count of months for a years and months duration.

date("1970-01-02").value
duration("P1M").value
date and time("1970-01-02T00:00:00").value

DMN 1.5 · August 2024

A small release whose most consequential change is invisible in expressions: type constraints stopped being value lists and became arbitrary boolean FEEL.

list replace(list, position, newItem)

Replaces a list element, addressed either by position or by a match function that decides which elements to replace.

list replace([2,4,7,8], 1, 5)
[5, 4, 7, 8] Try it ↑

Scientific notation

The grammar accepts exponent notation for numeric literals.

1.2e3
2.5E-2

DMN 1.4 · April 2023

A function-heavy release: string and context manipulation that previously needed a boxed invocation became a single built-in call.

string join(list) and string join(list, delimiter)

Concatenates the strings of a list, optionally separated by a delimiter.

string join(["a","b","c"], "-")
string join(["a","b","c"])

context put, context, context merge

Build and modify contexts without iterating: set or add an entry, build a context from key/value pairs, or combine several contexts into one.

context put({x: 1}, "y", 2)
{x=1, y=2} Try it ↑
context merge([{x: 1}, {y: 2}])
{x=1, y=2} Try it ↑

Rounding functions with a scale

round up, round down, round half up and round half down, each taking a number and the number of decimal places.

round up(1.234, 2)
round half down(1.5, 0)

now() and today()

Return the current moment and the current date.

today()
result depends on the evaluation moment Try it ↑
now()
result depends on the evaluation moment Try it ↑

DMN 1.3 · February 2021

The release improved time-based decisions: The full set of interval relations plus calendar extraction.

Temporal range functions

The complete set of interval relations, before, after, meets, met by, overlaps, overlaps before, overlaps after, starts, started by, finishes, finished by, during, includes, coincides over points and ranges alike.

before(1, 10)
during(5, [1..10])
includes([1..10], 5)

Calendar extraction functions

day of week, day of year, week of year and month of year read calendar properties off a date.

day of week(date("2026-08-13"))
Thursday Try it ↑
week of year(date("2026-08-13"))

Context introspection: get value and get entries

Read an entry whose name is only known at runtime, or expand a context into a list of key/value pairs to iterate over it.

get value({a: 1}, "a")
get entries({a: 1})
[{key=a, value=1}] Try it ↑

The dialect introduced in 1.6 has its own page: every engine-verified difference is listed under FEEL vs B-FEEL. For the current language as a whole, see the language constructs and the function reference.