elliptical-datetime
Version:
Elliptical phrases to handle natural language dates and times
344 lines (299 loc) • 11.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.InternalTime = exports.Time = exports.TimeOfDay = undefined;
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _moment = require('moment');
var _moment2 = _interopRequireDefault(_moment);
var _elliptical = require('elliptical');
var _ellipticalNumber = require('elliptical-number');
var _helpers = require('./helpers');
var _duration = require('./duration');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/** @jsx createElement */
const TimeOfDay = exports.TimeOfDay = {
describe() {
return (0, _elliptical.createElement)(
'placeholder',
{ label: 'time of day' },
(0, _elliptical.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 _lodash2.default.assign({}, option, { result: getTimeResult(option.result) });
}
const Time = exports.Time = {
id: 'elliptical-datetime:Time',
defaultProps: {
named: true,
recurse: true,
relative: true,
prepositions: false,
seconds: false,
nullify: false,
label: 'time'
},
describe({ props }) {
if (props.nullify) return null;
return (0, _elliptical.createElement)(
'map',
{ outbound: option => getTimeOptions(option, props), skipIncomplete: true },
(0, _elliptical.createElement)(InternalTime, props)
);
}
};
const InternalTime = exports.InternalTime = {
defaultProps: {
named: true,
recurse: true,
relative: true,
prepositions: false,
seconds: false,
nullify: false,
label: 'time'
},
describe({ props }) {
if (props.nullify) return null;
return (0, _elliptical.createElement)(
'choice',
null,
(0, _elliptical.createElement)(
'sequence',
null,
props.prepositions ? (0, _elliptical.createElement)(
'choice',
{ limit: 1 },
(0, _elliptical.createElement)('literal', { text: 'at ', decorate: true }),
(0, _elliptical.createElement)('literal', { text: 'from ' })
) : null,
(0, _elliptical.createElement)(
'placeholder',
{
label: props.label,
arguments: props.phraseArguments || (props.phraseArguments ? [props.phraseArgument] : [props.label]),
merge: true },
(0, _elliptical.createElement)(
'choice',
null,
(0, _elliptical.createElement)(AbsoluteNumeric, null),
(0, _elliptical.createElement)(AbsoluteRelativeHour, null),
(0, _elliptical.createElement)(AbsoluteNamed, null)
)
)
),
(0, _elliptical.createElement)(
'placeholder',
{
label: props.label,
arguments: props.phraseArguments || (props.phraseArguments ? [props.phraseArgument] : [props.label]) },
(0, _elliptical.createElement)(
'choice',
null,
props.named ? (0, _elliptical.createElement)(RelativeNamed, null) : null,
props.relative ? (0, _elliptical.createElement)(RelativeTime, null) : null,
props.recurse ? (0, _elliptical.createElement)(RecursiveTime, null) : null
)
)
);
}
};
const RelativeTime = {
mapResult(result) {
const duration = result.direction === -1 ? (0, _helpers.negateDuration)(result.duration) : result.duration;
return (0, _helpers.relativeTime)(duration);
},
describe({ props }) {
return (0, _elliptical.createElement)(
'choice',
null,
(0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)('literal', { text: 'in ', id: 'direction', value: 1 }),
(0, _elliptical.createElement)(_duration.TimeDuration, { id: 'duration', seconds: props.seconds })
),
(0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)(_duration.TimeDuration, { id: 'duration', seconds: props.seconds }),
(0, _elliptical.createElement)('literal', { text: ' from now', id: 'direction', value: 1 })
),
(0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)(_duration.TimeDuration, { id: 'duration', seconds: props.seconds }),
(0, _elliptical.createElement)('literal', { text: ' ago', id: 'direction', value: -1 })
)
);
}
};
const RelativeNamed = {
mapResult(result) {
return (0, _helpers.relativeTime)(result);
},
describe() {
return (0, _elliptical.createElement)('list', { items: [{ text: 'now', value: {} }, { text: 'right now', value: {} }], limit: 1 });
}
};
const AbsoluteTimeOfDay = {
mapValue(result) {
return (0, _helpers.coerceAmbiguousTime)(result.ambiguousTime, result.timeOfDay.range);
},
describe() {
return (0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)(
'choice',
{ id: 'ambiguousTime' },
(0, _elliptical.createElement)(AmbiguousAbsoluteNumeric, { seconds: props.seconds }),
(0, _elliptical.createElement)(AmbiguousAbsoluteRelativeHour, null)
),
(0, _elliptical.createElement)('literal', { text: ' in the ' }),
(0, _elliptical.createElement)(TimeOfDay, { id: 'timeOfDay' })
);
}
};
const AbsoluteNamed = {
mapResult(result) {
return (0, _helpers.absoluteTime)(result);
},
describe() {
return (0, _elliptical.createElement)('list', { items: [{ text: 'midnight', value: { hour: 0 } }, { text: 'noon', value: { hour: 12 } }] });
}
};
const AbsoluteNumeric = {
mapResult(result) {
const trueHour = parseInt(result.hour, 10);
const trueResult = _lodash2.default.assign({}, result, { hour: trueHour, minute: result.minute, second: result.second || 0 });
if (trueResult.ampm) {
const actualTime = (0, _helpers.ambiguousTime)(trueResult, trueResult.ampm);
return actualTime ? _lodash2.default.assign({}, actualTime, { _specificAMPM: trueResult.ampm }) : null;
} else {
if (trueResult.hour > 12) {
return (0, _helpers.ambiguousTime)(trueResult);
} else if (trueResult.hour === 0) {
return (0, _helpers.ambiguousTime)(trueResult);
} else {
return _lodash2.default.assign({}, trueResult, { _ambiguousAMPM: true });
}
}
},
filterResult(result) {
// console.log(result)
if (!result) {
return false;
}
if (result.hour > 23) {
return false;
}
return true;
},
defaultProps: {
minutes: true,
seconds: false
},
describe({ props }) {
return (0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)(Hour, { id: 'hour' }),
(0, _elliptical.createElement)(
'choice',
{ ellipsis: true, id: 'minute', limit: 1 },
(0, _elliptical.createElement)('literal', { text: ':00', decorate: true, value: 0 }),
props.minutes ? (0, _elliptical.createElement)(
'sequence',
{ optional: true, limited: true, merge: true },
(0, _elliptical.createElement)('literal', { text: ':' }),
(0, _elliptical.createElement)(MinutesOrSeconds, { merge: true })
) : null
),
(0, _elliptical.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' }] })
);
}
};
const AmbiguousAbsoluteRelativeHour = {
describe() {
return (0, _elliptical.createElement)(BaseAbsoluteRelativeHour, { ambiguous: true });
}
};
const AbsoluteRelativeHour = {
describe() {
return (0, _elliptical.createElement)(BaseAbsoluteRelativeHour, null);
}
};
const BaseAbsoluteRelativeHour = {
defaultProps: {
ambiguous: false
},
mapResult(result) {
const duration = result.direction === -1 ? (0, _helpers.negateDuration)(result.duration) : result.duration;
return (0, _helpers.relativeTime)(duration, result.absolute);
},
describe() {
return (0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)(
'placeholder',
{ label: 'number', id: 'duration' },
(0, _elliptical.createElement)(
'choice',
null,
(0, _elliptical.createElement)('list', { id: 'minutes', items: [{ text: 'quarter', value: 15 }, { text: 'half', value: 30 }] }),
(0, _elliptical.createElement)(_ellipticalNumber.Integer, { allowWordForm: true, id: 'minutes', min: 1, max: 59, merge: true, limit: 1 })
)
),
(0, _elliptical.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 }] }),
(0, _elliptical.createElement)(
'placeholder',
{ label: 'hour', id: 'absolute' },
(0, _elliptical.createElement)(
'choice',
null,
(0, _elliptical.createElement)(AbsoluteNumeric, { minutes: false }),
(0, _elliptical.createElement)(AbsoluteNamed, null)
)
)
);
}
};
const RecursiveTime = {
mapResult(result) {
const duration = result.direction === -1 ? (0, _helpers.negateDuration)(result.duration) : result.duration;
return (0, _helpers.relativeTime)(duration, result.time);
},
describe() {
return (0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)(
'sequence',
{ merge: true },
(0, _elliptical.createElement)(_duration.TimeDuration, { id: 'duration' }),
(0, _elliptical.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 })
),
(0, _elliptical.createElement)(Time, { recurse: false, relative: false, id: 'time' })
);
}
};
const MinutesOrSeconds = {
mapResult(result) {
return parseInt(result, 10);
},
describe() {
return (0, _elliptical.createElement)(_ellipticalNumber.DigitString, { label: 'minutes', max: 59, minLength: 2, maxLength: 2 });
}
};
const Hour = {
describe() {
return (0, _elliptical.createElement)(_ellipticalNumber.DigitString, { label: 'hour', min: 0, max: 24, maxLength: 2, minLength: 1, allowLeadingZeros: true });
}
};