UNPKG

elliptical-datetime

Version:

Elliptical phrases to handle natural language dates and times

332 lines (297 loc) 10.4 kB
/** @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 }); } };