Skip to content

Commit

Permalink
[PORT] [Expression] Add more timex builtin functions (#2187)
Browse files Browse the repository at this point in the history
* add more timex function

* fix typo

* fix typo
  • Loading branch information
Danieladu authored and boydc2014 committed May 7, 2020
1 parent c2e4eb9 commit 484eb78
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 0 deletions.
166 changes: 166 additions & 0 deletions libraries/adaptive-expressions/src/expressionFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,22 @@ export class ExpressionFunctions {
}
}

private static parseTimexProperty(timexExpr: any): {timexProperty: TimexProperty; error: string} {
let parsed: TimexProperty;
if (timexExpr instanceof TimexProperty) {
parsed = timexExpr;
} else if (typeof timexExpr === 'string'){
parsed = new TimexProperty(timexExpr);
} else {
parsed = new TimexProperty(timexExpr);
if (parsed === undefined || Object.keys(parsed).length === 0) {
return {timexProperty: parsed, error: `${ timexExpr } requires a TimexProperty or a string as a argument`};
}
}

return {timexProperty: parsed, error: undefined};
}

private static addOrdinal(num: number): string {
let hasResult = false;
let ordinalResult: string = num.toString();
Expand Down Expand Up @@ -2736,6 +2752,156 @@ export class ExpressionFunctions {
},
ReturnType.Number,
ExpressionFunctions.validateUnary),
new ExpressionEvaluator(
ExpressionType.IsDefinite,
(expr: Expression, state: any, options: Options): { value: any; error: string } => {
let parsed: TimexProperty;
let value = false;
let error: string;
let args: any [];
({args, error} = ExpressionFunctions.evaluateChildren(expr, state, options));
if (!error) {
({timexProperty: parsed, error: error} = ExpressionFunctions.parseTimexProperty(args[0]));
}

if (!error) {
value = parsed != undefined && parsed.year !== undefined && parsed.month !== undefined && parsed.dayOfMonth !== undefined;
}

return {value, error};
},
ReturnType.Boolean,
ExpressionFunctions.validateUnary),
new ExpressionEvaluator(
ExpressionType.IsTime,
(expr: Expression, state: any, options: Options): { value: any; error: string } => {
let parsed: TimexProperty;
let value = false;
let error: string;
let args: any [];
({args, error} = ExpressionFunctions.evaluateChildren(expr, state, options));
if (!error) {
({timexProperty: parsed, error: error} = ExpressionFunctions.parseTimexProperty(args[0]));
}

if (parsed && !error) {
value = parsed.hour !== undefined && parsed.minute !== undefined && parsed.second !== undefined;
}

return {value, error};
},
ReturnType.Boolean,
ExpressionFunctions.validateUnary),
new ExpressionEvaluator(
ExpressionType.IsDuration,
(expr: Expression, state: any, options: Options): { value: any; error: string } => {
let parsed: TimexProperty;
let value = false;
let error: string;
let args: any [];
({args, error} = ExpressionFunctions.evaluateChildren(expr, state, options));
if (!error) {
({timexProperty: parsed, error: error} = ExpressionFunctions.parseTimexProperty(args[0]));
}

if (parsed && !error) {
value = parsed.years !== undefined
|| parsed.months !== undefined
|| parsed.weeks !== undefined
|| parsed.days !== undefined
|| parsed.hours !== undefined
|| parsed.minutes !== undefined
|| parsed.seconds !== undefined;
}

return {value, error};
},
ReturnType.Boolean,
ExpressionFunctions.validateUnary),
new ExpressionEvaluator(
ExpressionType.IsDate,
(expr: Expression, state: any, options: Options): { value: any; error: string } => {
let parsed: TimexProperty;
let value = false;
let error: string;
let args: any [];
({args, error} = ExpressionFunctions.evaluateChildren(expr, state, options));
if (!error) {
({timexProperty: parsed, error: error} = ExpressionFunctions.parseTimexProperty(args[0]));
}

if (parsed && !error) {
value = (parsed.month !== undefined && parsed.dayOfMonth !== undefined) || parsed.dayOfWeek !== undefined;
}

return {value, error};
},
ReturnType.Boolean,
ExpressionFunctions.validateUnary),
new ExpressionEvaluator(
ExpressionType.IsTimeRange,
(expr: Expression, state: any, options: Options): { value: any; error: string } => {
let parsed: TimexProperty;
let value = false;
let error: string;
let args: any [];
({args, error} = ExpressionFunctions.evaluateChildren(expr, state, options));
if (!error) {
({timexProperty: parsed, error: error} = ExpressionFunctions.parseTimexProperty(args[0]));
}

if (parsed && !error) {
value = parsed.partOfDay !== undefined;
}

return {value, error};
},
ReturnType.Boolean,
ExpressionFunctions.validateUnary),
new ExpressionEvaluator(
ExpressionType.IsDateRange,
(expr: Expression, state: any, options: Options): { value: any; error: string } => {
let parsed: TimexProperty;
let value = false;
let error: string;
let args: any [];
({args, error} = ExpressionFunctions.evaluateChildren(expr, state, options));
if (!error) {
({timexProperty: parsed, error: error} = ExpressionFunctions.parseTimexProperty(args[0]));
}

if (parsed && !error) {
value = (parsed.year !== undefined && parsed.dayOfMonth === undefined) ||
(parsed.year !== undefined && parsed.month !== undefined && parsed.dayOfMonth === undefined) ||
(parsed.month !== undefined && parsed.dayOfMonth === undefined) ||
parsed.season !== undefined || parsed.weekOfYear !== undefined || parsed.weekOfMonth !== undefined;
}

return {value, error};
},
ReturnType.Boolean,
ExpressionFunctions.validateUnary),
new ExpressionEvaluator(
ExpressionType.IsPresent,
(expr: Expression, state: any, options: Options): { value: any; error: string } => {
let parsed: TimexProperty;
let value = false;
let error: string;
let args: any [];
({args, error} = ExpressionFunctions.evaluateChildren(expr, state, options));
if (!error) {
({timexProperty: parsed, error: error} = ExpressionFunctions.parseTimexProperty(args[0]));
}

if (parsed && !error) {
value = parsed.now !== undefined;
}

return {value, error};
},
ReturnType.Boolean,
ExpressionFunctions.validateUnary),

new ExpressionEvaluator(
ExpressionType.UriHost,
(expr: Expression, state: any, options: Options): { value: any; error: string } => {
Expand Down
9 changes: 9 additions & 0 deletions libraries/adaptive-expressions/src/expressionType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ export class ExpressionType {
public static readonly StartOfMonth: string = 'startOfMonth';
public static readonly Ticks: string = 'ticks';

// timex
public static readonly IsDefinite: string = 'isDefinite';
public static readonly IsTime: string = 'isTime';
public static readonly IsDuration: string = 'isDuration';
public static readonly IsDate: string = 'isDate';
public static readonly IsTimeRange: string = 'isTimeRange';
public static readonly IsDateRange: string = 'isDateRange';
public static readonly IsPresent: string = 'isPresent';

// Conversions
public static readonly Float: string = 'float';
public static readonly Int: string = 'int';
Expand Down
14 changes: 14 additions & 0 deletions libraries/adaptive-expressions/tests/badExpression.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,20 @@ const badExpressions =
'range(one, 0)', // second param should be more than 0

// Date and time function test
'isDefinite(12345)', // should hava a string or a TimexProperty parameter
'isDefinite(\'world\', 123445)', // should have only one parameter
'isTime(123445)', // should hava a string or a TimexProperty parameter
'isTime(\'world\', 123445)', // should have only one parameter
'isDuration(123445)', // should hava a string or a TimexProperty parameter
'isDuration(\'world\', 123445)', // should have only one parameter
'isDate(123445)', // should hava a string or a TimexProperty parameter
'isDate(\'world\', 123445)', // should have only one parameter
'isTimeRange(123445)', // should hava a string or a TimexProperty parameter
'isTimeRange(\'world\', 123445)', // should have only one parameter
'isDateRange(123445)', // should hava a string or a TimexProperty parameter
'isDateRange(\'world\', 123445)', // should have only one parameter
'isPresent(123445)', // should hava a string or a TimexProperty parameter
'isPresent(\'world\', 123445)', // should have only one parameter
'addDays(\'errortime\', 1)',// error datetime format
'addDays(timestamp, \'hi\')',// second param should be integer
'addDays(timestamp)',// should have 2 or 3 params
Expand Down
24 changes: 24 additions & 0 deletions libraries/adaptive-expressions/tests/expressionParser.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/no-var-requires */
const { Expression, SimpleObjectMemory, ExpressionFunctions, Options } = require('../lib');
var { TimexProperty } = require('@microsoft/recognizers-text-data-types-timex-expression');
const assert = require('assert');
const moment = require('moment');

Expand Down Expand Up @@ -405,6 +406,23 @@ const dataSource = [
// Otherwise exceptions will be thrown out
// All the output timestamp strings are in ISO format of YYYY-MM-DDTHH:mm:ss.sssZ
// Init dateTime: 2018-03-15T13:00:00:111Z
['isDefinite(\'helloworld\')', false],
['isDefinite(\'2012-12-21\')', true],
['isDefinite(\'xxxx-12-21\')', false],
['isDefinite(validFullDateTimex)', true],
['isDefinite(invalidFullDateTimex)', false],
['isTime(validHourTimex)', true],
['isTime(invalidHourTimex)', false],
['isDuration(\'PT30M\')', true],
['isDuration(\'2012-12-21T12:30\')', false],
['isDate(\'PT30M\')', false],
['isDate(\'2012-12-21T12:30\')', true],
['isTimeRange(\'PT30M\')', false],
['isTimeRange(validTimeRange)', true],
['isDateRange(\'PT30M\')', false],
['isDateRange(\'2012-02\')', true],
['isPresent(\'PT30M\')', false],
['isPresent(validNow)', true],
['addDays(timestamp, 1)', '2018-03-16T13:00:00.111Z'],
['addDays(timestamp, 1,\'MM-dd-yy\')', '03-16-18'],
['addHours(timestamp, 1)', '2018-03-15T14:00:00.111Z'],
Expand Down Expand Up @@ -691,6 +709,12 @@ const scope = {
],
timestamp: '2018-03-15T13:00:00.111Z',
notISOTimestamp: '2018-03-15T13:00:00Z',
validFullDateTimex: new TimexProperty('2020-02-20'),
invalidFullDateTimex: new TimexProperty('xxxx-02-20'),
validHourTimex: new TimexProperty('2020-02-20T07:30'),
validTimeRange: new TimexProperty({partOfDay: 'morning'}),
validNow: new TimexProperty({now: true}),
invalidHourTimex: new TimexProperty('2001-02-20'),
timestampObj: new Date('2018-03-15T13:00:00.000Z'),
unixTimestamp: 1521118800,
user:
Expand Down

0 comments on commit 484eb78

Please sign in to comment.