Being able to handle date and time expressions is crucial for many applications. Think of bots for travel booking or insurance claims for example. Teneo provides a DateTime Handler that can be used to catch date and time expressions from the user input. The DateTime Handler is included in the Teneo Lexical Resources.
Many date and time expressions have to be interpreted with respect to an anchor date and time. For example, 'tomorrow' denotes different dates depending on when it has been said. The following table contains some examples returned by the DateTime Handler. DateTime expression is what the user said, DateTime representation1 reflects what the DateTime library caught, and DateTime interpretation is a map containing Java LocalDates and Java LocalTimes returned by the interpretation script. Note that the assumed anchor date for the interpretations below was June 8th 2021:
DateTime expression | DateTime representation1 | DateTime interpretation |
---|---|---|
Tomorrow | [ date: [ named_relative: tomorrow ]] | [ date: [ start: [ 2021-06-09 ], type: point ] time: [ start: [ 00:00 ]]] |
August 19th, 2021 | [ date: [ month: 8, day_of_month: 19, year: 2021 ]] | [ date: [ start: [ 2021-08-19 ], type: point ] time: [ start: [ 00:00 ]]] |
Monday at 3 o'clock | [ date: [ weekday: mon ], time: [ hour:3, meridiem: ampm ]] |
[ date: [ start: [ 2021-06-14 ], type: point ], time: [ start: [ 03:00, 15:00 ], type: point ]] |
Today, between 15:30 and 16:15 |
[ date: [ named_relative: today ], time: [ relation: between, time1: [ hour: 3, meridiem: pm, minute: 30 ], time2: [ hour: 4, meridiem: pm, minute: 15 ]]] |
[ date: [ start: [ 2021-06-08 ], type: point ], time: [ start: [ 15:30 ], end: [ 16:15 ], type: range ]] |
As you can see from the examples, there are cases where it is not clear which exact time the user meant. In such cases, the interpretation simply contains both alternatives, "03:00" and "15:00", for "3 o'clock". The ambiguity can then be resolved in the solution, if needed.
The DateTime library is assigned as soon as you have assigned the Lexical Resource. Visual instructions of how to do that can be found here.
In the following, we will build a simple example flow that makes use of the DateTime Handler to book tables.
We will first set up the basic flow structure:
Book a table
.I want to book a table
.I want to book a table
I would like to book a table
I'd like to book a table
Can I book a table
Can I make a reservation for a table
Could I book a table
When?
. Paste When do you want to book it?
into the 'Answers' text field. Interpret date and time
.Booking confirmation
.This is how your flow should now look:
In the following, we will add content to the empty nodes and add conditions to the transitions.
Teneo's DateTime library features numerous different language objects that can be used to catch date and time expressions in the user input. Some of these are illustrated in the table below. Depending on which kind of DateTime expressions you are expecting from the user, i.e only date or only time or only weekdays, you may use different language objects. All language objects in the English DateTime library start with the prefix 'DT'. You can thus simply search for DT*
in Teneo's search interface (prefixes for languages other than English can be found in the grey box below), to see all language objects that belong to the DateTime library. We recommend to start from the main object, DT_DATE_TIME.REC and then click your way through the language objects used there and continue doing so until you find the level of granularity that you were looking for.
Language Object Name | Coverage | Examples |
---|---|---|
%DT_DATE_TIME.REC | Combinations of date and time expressions | 18:30 on August 14th, Tomorrow at 5 o'clock |
%DT_DATE.REC | Date expressions | 14.08.2019, Monday next week, five days from now |
%DT_TIME.REC | Time expressions | 13:40, at quarter past eight, at 5pm |
The DateTime Handler is available in the following languages:
Chinese, Danish, Dutch, English, French, German, Italian, Japanese, Norwegian, Portuguese, Spanish, and Swedish.
More info can be found in the documentation.
In our example, we will use the most general one, DT_DATE_TIME.REC:
dateTimeRepresentation
to your flow and assign it the default value [:]
. Get date and time
.%DT_DATE_TIME.REC^{dateTimeRepresentation = lob.datetime}
.While it's not fully functional yet, you can now use the output node 'Booking confirmation' to print the intermediate DateTime representation:
Great! I booked a table for ${dateTimeRepresentation}
in the 'Answers' text field.You should now get the following response:
User: I want to book a table
Bot: When do you want to book it?
User: Tomorrow, 6:30.
Bot: Great! I booked a table for [ date: [ named_relative: tomorrow ], time: [ hour: 6, meridiem: ampm, minute: 30 ]]
Note that this is the intermediate DateTime representation that simply reflects what the user said. This representation is not really meant to be printed to the user. We just wanted to show you what happens internally here. For example, you can see that the time expression '6:30' is ambiguous with respect to am/pm. We will show you below how you can resolve such ambiguities. In order to get an actual date and time, this representation needs to be handed over to the interpreter. In the next section, we will show you how this is done.
Go back to the 'Book a table' flow in edit mode. Then:
dateTime
and assign it the default value [:]
.dateTime = datetime.Handler.interpret(dateTimeRepresentation)
into the 'Execution Script' field.Booking confirmation
node, replace the existing answer with: Great! I booked a table for ${dateTime.time.start[0]} on ${dateTime.date.start[0]}
. This selects the first time point ('time.start[0]') and the first date point ('date.start[0]') from the date time map that the interpreter returned and prints it to the user in a more readable format.Now go ahead and give it a try in Try Out! For the dialogue above, you should now get the following answer (assuming you spoke to the bot on June 8th):
User: I want to book a table.
Bot: When do you want to book it?
User: Tomorrow, 6:30.
Bot: Great! I booked a table for 6:30 on 2021-06-08.
Note that the expression 'DateTime.time.start[0]' picks the first available start time that the interpreter script returned. However, as you have seen from the internal representation above, this time expression was ambiguous with respect to am/pm ( 'meridiem : ampm' ). In the following, we illustrate some disambiguation strategies.
Many time expressions like "6:30" or "3 o'clock" are ambiguous as to whether they denote 'am' or 'pm'. The DateTimeInterpreter returns both possible times for such expressions: "06:30" and "18:30". However, for many applications it is crucial to correctly disambiguate such time expressions. We will illustrate two disambiguation strategies here that you may use in your solution. One is to disambiguate the representation before sending it to the interpretation script, and the other one is to disambiguate what the interpretation script returned.
The safest way to disambiguate a time expression is to let the user disambiguate it. The fact that time expressions are ambiguous with respect to 'am'/'pm' is visible from the intermediate DateTime representation. Thus, it can be resolved there before it is handed over to the DateTime interpretation script:
Resolve ambiguity
.The basic structure is now in place. Time to fill the transitions with content! We will start with the first one.
Ambiguous Time
.{dateTimeRepresentation.containsKey('time') && dateTimeRepresentation.time.meridiem=='ampm'}
into the condition field. This condition is fulfilled if the DateTime expression holds a time and if this times does not hold a specified 'am' or 'pm'.Now that we are done with our first transition, it is time for the second one.
Resolve am/pm
.(am)^{dateTimeRepresentation.time.meridiem='am'}
/
(pm)^{dateTimeRepresentation.time.meridiem='pm'}
That's it. You should now get the following dialogue:
User: I want to book a table.
Bot: When do you want to book it?
User: Tomorrow, 6:30.
Bot Do you mean 6 am or pm?
User: pm
Bot: Great! I booked a table for 18:30 on 2021-06-09.
In the previous section we have shown how the decision about 'am' vs 'pm' can be returned to the user to request clarification. Sometimes however, the context only allows one interpretation and in such cases we should avoid asking the user. Let's say that we still want to book a table. As the restaurant is open from 5pm to 11pm, all table bookings will denote 'pm'. In cases where the DateTime interpreter returns more than one possible time, we will thus always select 'pm'.
This is how we will go about: before returning the DateTime interpreter's answer to the user, we will select the 'pm' time, if applicable. Whenever two times are returned, the second one (at index 1) is always 'pm'. If this is the case, we copy the 'pm' value from index 1 to index 0. This way, we do not have to modify the output node:
if (dateTime.time.start[1]) {
dateTime.time.start[0] = dateTime.time.start[1]
}
That's it. When talking to your bot, you should now always get the 'pm' interpretation for ambiguous time expressions like 6:30:
User: I want to book a table.
Bot: When do you want to book it?
User: Tomorrow, 6:30.
Bot: Great! I booked a table for 18:30 on 2021-06-09.
For some date and time expressions the interpretation depends on the conversation context. For example, the expression 'on Wednesday' may be interpreted as a date in the past or in the future. The following example dialogue happened on Friday, June 25th 2021:
User: I arrived in Barcelona on Wednesday.
Bot: You mean 2021-06-30, right?
User: I will arrive in Barcelona on Wednesday.
Bot: You mean 2021-06-30, right?
By default, the interpretation direction is 'forward', so 'on Wednesday' would be interpreted as the following Wednesday. It is possible to change this interpretation direction to 'back' in order to point to the previous Wednesday instead. We will show you how to edit the default interpretation direction in the next section. Here, we will show you how you can take advantage of the verb tense to make an appropriate decision. One component of the Teneo Input Processing Chain assigns part-of-speech tags to all words of the user input. We will make use of one of these tags, %$PAST.POS, which indicates that a verb occurred in past tense in order to set the interpretation direction to 'back'. In the following, we build a small example flow in order to illustrate the functionality:
Disambiguate Interpretation Direction
.dateTimeRepresentation
and assign it the default value [:]
. It will store the representation of the DateTime expression uttered by the user.pastTense
and assign it the default value null
. This one will store whether or not a past tense tag was found in the user input.dateTime
and assign it the default value null
. It will store the DateTime interpretation.Now that the variables are created, let us proceed with building the flow structure.
DateTime + Tense
. %DT_DATE_TIME.REC^{dateTimeRepresentation=lob.datetime}
&^
(%$PAST.POS^{pastTense = true}):o
Call Interpreter
and make it the Start node by clicking 'Set Start Node' in the top ribbon.dateTime = pastTense?datetime.Handler.interpret(dateTimeRepresentation, "back"): datetime.Handler.interpret(dateTimeRepresentation)
This will call the interpreter with the interpretation direction 'back' if the pastTense variable has been set in the Trigger condition. Otherwise, the interpreter will be called with the default interpretation direction "forward" (which does not need to be explicitly specified).
You mean ${DateTime.date.start[0]}, right?
into the Output node and name it You mean ... right?
.Anchor date
By default, the DateTime interpretation script assumes the current day to be the anchor date for relative date expressions like 'tomorrow' or 'Monday next week'. Should it be necessary for you to change this anchor date, you can do so by adding the desired anchor date to the DateTime interpreter call. Say you want "14th of August 2019" to be your anchor date. Then, the DateTime interpreter call in the script node of your flow will look like this: dateTime = datetime.Handler.interpret(dateTimeRepresentation, "2019-08-14")
. Please note that the new anchor date must be passed in ISO-8601 format and put into quotes (""). If you want to change the anchor date globally for the whole solution, go to the global pre-processing script and paste datetime.Handler.setAnchor("2019-08-14")
. Note that you have to restart the conversation before changes in the global script will apply.
Anchor time
You may not only modify the anchor date, but also the anchor time, if necessary. In order to do so, simply add the time to the anchor date by keeping the ISO-8601 format, like so: dateTime = datetime.Handler.interpret(dateTimeRepresentation, "2018-11-21T1630")
. The first two digits after the 'T' denote the hour and the last two digits the minutes of the anchor time.
Interpretation direction
For some expressions, like 'on Monday' or 'in September', the interpretation depends on the context. They may denote a date in the past or in the future. Depending on the domain for which you created your bot, different interpretation directions might be appropriate. For example, in our table booking domain, one can assume that all dates occurring in the conversation denote future events. However, in an insurance claim domain a backwards interpretation direction is more suitable. By default the interpretation direction is set to 'forward', but you can change it to 'back' by adding it to the DateTime interpreter call: dateTime = datetime.Handler.interpret(dateTimeRepresentation, "back")
.
Both
You may also change both the anchor date and the interpretation direction at once: dateTime = datetime.Handler.interpret(dateTimeRepresentation, "2018-11-21T1630", "back")
.
The DateTime Handler covers a wide range of different date and time expressions and it always returns the most plausible interpretation. However, if necessary, you may adapt the DateTime Handler to, for example, recognize named days or adjust the interpretation of existing dates and times. For more information, read this page on Advanced Usage.
Was this page helpful?