elliptical-datetime
Version:
Elliptical phrases to handle natural language dates and times
332 lines (297 loc) • 10.4 kB
JavaScript
/** @jsx createElement */
import _ from 'lodash';
import moment from 'moment';
import { createElement } from 'elliptical';
import { DigitString, Integer } from 'elliptical-number';
import { absoluteTime, ambiguousTime, coerceAmbiguousTime, negateDuration, relativeTime } from './helpers';
import { TimeDuration } from './duration';
export var TimeOfDay = {
describe: function describe() {
return createElement(
'placeholder',
{ label: 'time of day' },
createElement('list', { items: [{ text: 'early morning', value: { default: 6, impliedAMPM: 'am' } }, { text: 'morning', value: { default: 8, impliedAMPM: 'am' } }, { text: 'late morning', value: { default: 10, impliedAMPM: 'am' } }, { text: 'afternoon', value: { default: 12, impliedAMPM: 'pm' } }, { text: 'late afternoon', value: { default: 15, impliedAMPM: 'pm' } }, { text: 'evening', value: { default: 17, impliedAMPM: 'pm' } }, { text: 'night', value: { default: 20, impliedAMPM: 'pm' } }] })
);
}
};
function getTimeResult(result) {
return { hour: result.hour, minute: result.minute, second: result.second };
}
function getTimeOptions(option, props) {
return _.assign({}, option, { result: getTimeResult(option.result) });
}
export var Time = {
id: 'elliptical-datetime:Time',
defaultProps: {
named: true,
recurse: true,
relative: true,
prepositions: false,
seconds: false,
nullify: false,
label: 'time'
},
describe: function describe(_ref) {
var props = _ref.props;
if (props.nullify) return null;
return createElement(
'map',
{ outbound: function outbound(option) {
return getTimeOptions(option, props);
}, skipIncomplete: true },
createElement(InternalTime, props)
);
}
};
export var InternalTime = {
defaultProps: {
named: true,
recurse: true,
relative: true,
prepositions: false,
seconds: false,
nullify: false,
label: 'time'
},
describe: function describe(_ref2) {
var props = _ref2.props;
if (props.nullify) return null;
return createElement(
'choice',
null,
createElement(
'sequence',
null,
props.prepositions ? createElement(
'choice',
{ limit: 1 },
createElement('literal', { text: 'at ', decorate: true }),
createElement('literal', { text: 'from ' })
) : null,
createElement(
'placeholder',
{
label: props.label,
arguments: props.phraseArguments || (props.phraseArguments ? [props.phraseArgument] : [props.label]),
merge: true },
createElement(
'choice',
null,
createElement(AbsoluteNumeric, null),
createElement(AbsoluteRelativeHour, null),
createElement(AbsoluteNamed, null)
)
)
),
createElement(
'placeholder',
{
label: props.label,
arguments: props.phraseArguments || (props.phraseArguments ? [props.phraseArgument] : [props.label]) },
createElement(
'choice',
null,
props.named ? createElement(RelativeNamed, null) : null,
props.relative ? createElement(RelativeTime, null) : null,
props.recurse ? createElement(RecursiveTime, null) : null
)
)
);
}
};
var RelativeTime = {
mapResult: function mapResult(result) {
var duration = result.direction === -1 ? negateDuration(result.duration) : result.duration;
return relativeTime(duration);
},
describe: function describe(_ref3) {
var props = _ref3.props;
return createElement(
'choice',
null,
createElement(
'sequence',
null,
createElement('literal', { text: 'in ', id: 'direction', value: 1 }),
createElement(TimeDuration, { id: 'duration', seconds: props.seconds })
),
createElement(
'sequence',
null,
createElement(TimeDuration, { id: 'duration', seconds: props.seconds }),
createElement('literal', { text: ' from now', id: 'direction', value: 1 })
),
createElement(
'sequence',
null,
createElement(TimeDuration, { id: 'duration', seconds: props.seconds }),
createElement('literal', { text: ' ago', id: 'direction', value: -1 })
)
);
}
};
var RelativeNamed = {
mapResult: function mapResult(result) {
return relativeTime(result);
},
describe: function describe() {
return createElement('list', { items: [{ text: 'now', value: {} }, { text: 'right now', value: {} }], limit: 1 });
}
};
var AbsoluteTimeOfDay = {
mapValue: function mapValue(result) {
return coerceAmbiguousTime(result.ambiguousTime, result.timeOfDay.range);
},
describe: function describe() {
return createElement(
'sequence',
null,
createElement(
'choice',
{ id: 'ambiguousTime' },
createElement(AmbiguousAbsoluteNumeric, { seconds: props.seconds }),
createElement(AmbiguousAbsoluteRelativeHour, null)
),
createElement('literal', { text: ' in the ' }),
createElement(TimeOfDay, { id: 'timeOfDay' })
);
}
};
var AbsoluteNamed = {
mapResult: function mapResult(result) {
return absoluteTime(result);
},
describe: function describe() {
return createElement('list', { items: [{ text: 'midnight', value: { hour: 0 } }, { text: 'noon', value: { hour: 12 } }] });
}
};
var AbsoluteNumeric = {
mapResult: function mapResult(result) {
var trueHour = parseInt(result.hour, 10);
var trueResult = _.assign({}, result, { hour: trueHour, minute: result.minute, second: result.second || 0 });
if (trueResult.ampm) {
var actualTime = ambiguousTime(trueResult, trueResult.ampm);
return actualTime ? _.assign({}, actualTime, { _specificAMPM: trueResult.ampm }) : null;
} else {
if (trueResult.hour > 12) {
return ambiguousTime(trueResult);
} else if (trueResult.hour === 0) {
return ambiguousTime(trueResult);
} else {
return _.assign({}, trueResult, { _ambiguousAMPM: true });
}
}
},
filterResult: function filterResult(result) {
// console.log(result)
if (!result) {
return false;
}
if (result.hour > 23) {
return false;
}
return true;
},
defaultProps: {
minutes: true,
seconds: false
},
describe: function describe(_ref4) {
var props = _ref4.props;
return createElement(
'sequence',
null,
createElement(Hour, { id: 'hour' }),
createElement(
'choice',
{ ellipsis: true, id: 'minute', limit: 1 },
createElement('literal', { text: ':00', decorate: true, value: 0 }),
props.minutes ? createElement(
'sequence',
{ optional: true, limited: true, merge: true },
createElement('literal', { text: ':' }),
createElement(MinutesOrSeconds, { merge: true })
) : null
),
createElement('list', { unique: true, id: 'ampm', limit: 2, items: [{ text: ' am', value: 'am' }, { text: 'am', value: 'am' }, { text: ' a', value: 'am' }, { text: 'a', value: 'am' }, { text: ' a.m.', value: 'am' }, { text: 'a.m.', value: 'am' }, { text: ' a.m', value: 'am' }, { text: 'a.m', value: 'am' }, { text: ' pm', value: 'pm' }, { text: 'pm', value: 'pm' }, { text: ' p', value: 'pm' }, { text: 'p', value: 'pm' }, { text: ' p.m.', value: 'pm' }, { text: 'p.m.', value: 'pm' }, { text: ' p.m', value: 'pm' }, { text: 'p.m', value: 'pm' }] })
);
}
};
var AmbiguousAbsoluteRelativeHour = {
describe: function describe() {
return createElement(BaseAbsoluteRelativeHour, { ambiguous: true });
}
};
var AbsoluteRelativeHour = {
describe: function describe() {
return createElement(BaseAbsoluteRelativeHour, null);
}
};
var BaseAbsoluteRelativeHour = {
defaultProps: {
ambiguous: false
},
mapResult: function mapResult(result) {
var duration = result.direction === -1 ? negateDuration(result.duration) : result.duration;
return relativeTime(duration, result.absolute);
},
describe: function describe() {
return createElement(
'sequence',
null,
createElement(
'placeholder',
{ label: 'number', id: 'duration' },
createElement(
'choice',
null,
createElement('list', { id: 'minutes', items: [{ text: 'quarter', value: 15 }, { text: 'half', value: 30 }] }),
createElement(Integer, { allowWordForm: true, id: 'minutes', min: 1, max: 59, merge: true, limit: 1 })
)
),
createElement('list', { limit: 2, id: 'direction', items: [{ text: ' past ', value: 1 }, { text: ' to ', value: -1 }, { text: ' of ', value: -1 }, { text: ' til ', value: -1 }, { text: ' before ', value: -1 }, { text: ' from ', value: -1 }] }),
createElement(
'placeholder',
{ label: 'hour', id: 'absolute' },
createElement(
'choice',
null,
createElement(AbsoluteNumeric, { minutes: false }),
createElement(AbsoluteNamed, null)
)
)
);
}
};
var RecursiveTime = {
mapResult: function mapResult(result) {
var duration = result.direction === -1 ? negateDuration(result.duration) : result.duration;
return relativeTime(duration, result.time);
},
describe: function describe() {
return createElement(
'sequence',
null,
createElement(
'sequence',
{ merge: true },
createElement(TimeDuration, { id: 'duration' }),
createElement('list', { id: 'direction', items: [{ text: ' before ', value: -1 }, { text: ' after ', value: 1 }, { text: ' from ', value: 1 }, { text: ' past ', value: 1 }, { text: ' to ', value: -1 }, { text: ' of ', value: -1 }, { text: ' til ', value: -1 }], limit: 2 })
),
createElement(Time, { recurse: false, relative: false, id: 'time' })
);
}
};
var MinutesOrSeconds = {
mapResult: function mapResult(result) {
return parseInt(result, 10);
},
describe: function describe() {
return createElement(DigitString, { label: 'minutes', max: 59, minLength: 2, maxLength: 2 });
}
};
var Hour = {
describe: function describe() {
return createElement(DigitString, { label: 'hour', min: 0, max: 24, maxLength: 2, minLength: 1, allowLeadingZeros: true });
}
};