AI Zone Admin Forum Add your forum

NEWS: Chatbots.org survey on 3000 US and UK consumers shows it is time for chatbot integration in customer service!read more..

How to parse date and time strings?
 
 

Hi everyone,

I’m using RiveScript in combination with Node and Telegram.
I want to parse and save a date or/and time user input and I’m currently struggling with the missing dots and colons which are stripped off by the RegExp.

In the RS vs. AIML comparison I found this sentence:

This isn’t implemented in RiveScript because the exact formatting of a date/time stamp is subjective and should be left to the writer, and handled through the use of objects instead.

But I have no Idea how I would process date and time variables inside objects without colons and dots.
I know I could change the RegExp, so it would ignore dots and colons, but this would mess up the rest of the defined answers.

Another idea I had, was to process the date and time inputs before passing it to RiveScript, but I don’t think that would be the best way.

Does anybody already worked with time and date variables?

 

 
  [ # 1 ]

If you enable UTF-8 support (by setting `utf8: true` in the constructor, like `var rs = new RiveScript({utf8: true})`, then user messages are only filtered for a very minimal set of characters (some punctuation characters defined by the `unicodePunctuation` regexp, the backslash “\” and HTML angle brackets “<” and “>”).

The default set of unicode punctuation includes the : symbol, but you can provide your own set so it doesn’t interfere with date/time symbols.

var bot = new RiveScript({utf8true});
bot.unicodePunctuation = new RegExp(/[.,!?;]/g); // same as default, minus the : 

So then the user’s time shouldn’t get too mangled in their message.

- - -

In the AIML/RS comparison it was talking about the `<date>` tag from AIML, i.e. as used in an AIML template:

<category>
  <
pattern>WHAT TIME IS IT</pattern>
  <
template>It is currently: <date /></template>
</
category

It might produce a reply like “It is currently: Thursday April 28 2016 4:11 PM”, but the exact formatting of that isn’t well defined (AFAIK, I didn’t check the AIML spec), it doesn’t seem to provide a way to customize the formatting of the output and seems like it’d be an implementation detail.

RiveScript doesn’t have the `<date>` tag for replies because you can easily enough do that with an object macro, like

what time is it
It is currently <call>date</call>

object date python
    import datetime
    
return datetime.datetime.now().strftime("%H:%M:%S")
object 

So, that note on the AIML vs RS doesn’t involve parsing dates, just rendering them as part of a reply.

 

 
  [ # 2 ]
Noah Petherbridge - Apr 29, 2016:

It might produce a reply like “It is currently: Thursday April 28 2016 4:11 PM”, but the exact formatting of that isn’t well defined (AFAIK, I didn’t check the AIML spec), it doesn’t seem to provide a way to customize the formatting of the output and seems like it’d be an implementation detail.

Details of the AIML date tag including formatting the output can be found here: http://www.alicebot.org/aiml/aaa/Date.txt

 

 
  [ # 3 ]

@Steve: good to know. It looks like a Pandorabots extension?

The last time I touched AIML seriously was with Alicebot Program D, where the `<date>` tag was really simple and didn’t have any attributes.

It looks like the AIML 1.0.1 working draft didn’t specify any attributes for it:

7.1.8.1. Date

The date element tells the AIML interpreter that it should substitute the system local date and time. No formatting constraints on the output are specified.

The date element does not have any content.

<!—Category: aiml-template-elements—>

<aiml:date>

 

 
  [ # 4 ]

It might produce a reply like “It is currently: Thursday April 28 2016 4:11 PM”, but the exact formatting of that isn’t well defined (AFAIK, I didn’t check the AIML spec), it doesn’t seem to provide a way to customize the formatting of the output and seems like it’d be an implementation detail.

My mistake, I thought <date> would be an input format, not an output.

- - -

I have UTF8 enabled and also tried the RegExp trick, but in order to parse date formats my RegExp would look like this:

new RegExp(/[,!?;]/g// without : and . 

This would work for date/time parsing, but would be a problem for the rest of the chatbot when dots are not getting stripped off.

Perfect would be something like this:

set the event on at *
- <
call>parseDateTime <raw1> <raw2></call>OkI saved that 

 

 

 
  [ # 5 ]

You might have to handle this out-of-band somehow (store the user’s raw message somewhere else in your program, access it from the object macro, etc.)

Tags like `<raw1>` wouldn’t really work either. Under the hood RiveScript uses a regular expression to match the user’s message, and <star1> etc. are just the regexp captured groups (like $1, $2, etc.). To be able to support a `<raw>` tag the regexp would have to be evaluated twice—once against their filtered message for <star> and again for their raw message for <raw>. The problem though is this double-evaluation would be unpredictable; a user’s raw message, including punctuation and such, might not match the same trigger regexp that their filtered one did.

Some old ancestor of RiveScript stored a copy of the user’s raw message somewhere else, so an object macro could get their full raw message and do their own parsing on it, but that’s not currently built in. So for now you could handle that out-of-band; for example, store it in some variable accessible from the `this` variable in JS, and pass in `this` as the scope parameter to `reply()`. It’s a bit tricky to explain but there’s an example here: https://github.com/aichaos/rivescript-js/tree/master/eg/scope

 

 
  [ # 6 ]

I just finished something similar :D

First I made a new RegExp ...

function regExpRawFormat(literal_string{
  
return literal_string.replace(/[-[\]{}()*+!<=?\/\\^$|#]/g, '\\$&'); // without : . , \s

... and saved the input (parsed by the new RegExp) into a userVar ...

botRS.setUservar(chatId'rawMsg'regExpRawFormat(message)); 

... now I can access it inside the .rive files

<set dateOfEvent=<get rawMsg>><call>saveDateTime dateOfEvent</call

Only negative aspect: it saves always the whole message.

 

 
  [ # 7 ]

Yeah it’d save the whole message. When RiveScript supported storing away the raw message, the situation was the same.

So you’d have to do like,

set time to *
- <
call>setTime</call>

object setTime javascript
    
var rawMsg rs.getUservar(rs.currentUser(), "rawMsg");
    var 
match rawMsg.match(/^set time to (.+?)$/i);
    var 
timestamp match[1];
    
// do something with it
object 
 

 
  [ # 8 ]

I’m using chrono, so in this case it’s no problem to save the whole message, chrono takes care of it:

- <set dateOfEvent=<get rawMsg>><call>

object saveDateTime javascript
  
var chrono = require('chrono-node');
  var 
string =  rs.getUservar(rs.currentUser(), args[0]);
  var 
dateTime chrono.parseDate(string);
  
rs.setUservar(rs.currentUser(), 'dateOfEvent'dateTime);
object 

But I can imagine some other cases, where you have to do it the same way as in your example.
Maybe it would be useful sending the trigger-text (“set time to”) to the object, so you don’t have to write it twice.

 

 
  login or register to react