elliptical-datetime
Version:
Elliptical phrases to handle natural language dates and times
219 lines (190 loc) • 7.91 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Range = undefined;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** @jsx createElement */
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _moment = require('moment');
var _moment2 = _interopRequireDefault(_moment);
var _elliptical = require('elliptical');
var _helpers = require('./helpers');
var _datetime = require('./datetime');
var _duration = require('./duration');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const TrueDateTime = {
describe({ props }) {
return (0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)('literal', { text: 'all day ', id: 'allDay', value: true, optional: true, limited: true }),
(0, _elliptical.createElement)(
'choice',
{ merge: true },
(0, _elliptical.createElement)(_datetime.InternalDateTime, _extends({}, props, { id: undefined })),
(0, _elliptical.createElement)(
'map',
{ 'function': result => ({ dateTime: result }) },
(0, _elliptical.createElement)(_datetime.DateTime, _extends({}, props, { nullify: true }))
)
)
);
}
};
function* mapRangeResults(result, props) {
if (result.start && result.end) {
if (!result.start.time && !result.end.time) {
for (let startDate of (0, _helpers.possibleDates)(result.start)) {
for (let endDate of (0, _helpers.possibleDates)(result.end)) {
yield {
start: (0, _helpers.join)(startDate, { hour: 0, minute: 0, second: 0 }, props.timezoneOffset),
end: (0, _helpers.join)(endDate, { hour: 0, minute: 0, second: 0 }, props.timezoneOffset),
allDay: true
};
}
}
} else {
for (let startDate of (0, _helpers.possibleDates)(result.start, result.end.date)) {
for (let endDate of (0, _helpers.possibleDates)(result.end, startDate)) {
yield {
start: (0, _helpers.join)(startDate, result.start.time || props.defaultTime, props.timezoneOffset),
end: (0, _helpers.join)(endDate, result.end.time || props.defaultTime, props.timezoneOffset),
allDay: false
};
}
}
}
} else if (result.start && result.duration) {
for (let startDate of (0, _helpers.possibleDates)(result.start)) {
const start = (0, _helpers.join)(startDate, result.start.time || props.defaultTime, props.timezoneOffset);
yield {
start,
end: (0, _moment2.default)(start).add(result.duration).toDate(),
allDay: false
};
}
} else if (result.start) {
if (!result.start.time) {
for (let startDate of (0, _helpers.possibleDates)(result.start)) {
yield {
start: startDate,
end: startDate,
allDay: true
};
}
} else {
for (let startDate of (0, _helpers.possibleDates)(result.start)) {
const start = (0, _helpers.join)(startDate, result.start.time, props.timezoneOffset);
yield {
start: start,
end: (0, _moment2.default)(start).add(props.defaultDuration).toDate(),
allDay: false
};
}
}
}
}
function preprocessRangeAmbiguity(result, props) {
if (result.start && result.end) {
if (result.end.date && result.end._ambiguousMonth) {
const trueEndDate = (0, _moment2.default)(result.end.date).month((0, _moment2.default)(result.start.date).month()).toDate();
const end = _lodash2.default.assign({}, result.end, { date: trueEndDate });
return _lodash2.default.assign({}, result, { end });
}
if (result.start._ambiguousAMPM && result.end._specificAMPM) {
const start = _lodash2.default.clone(result.start);
start.time = (0, _helpers.ambiguousTime)(result.start.time, result.end._specificAMPM);
return _lodash2.default.assign({}, result, { start });
}
}
return result;
}
function* mapRangeOptions(option, props) {
const processedResult = preprocessRangeAmbiguity(option.result, props);
for (let result of mapRangeResults(processedResult, props)) {
yield _lodash2.default.assign({}, option, { result });
}
}
function filterRangeOption(option) {
const result = option.result;
// console.log(result)
// it doesn't make any sense to specify a "date to time" or "time to date"
if (result.start && result.end && (result.start.date && !result.start.time && !result.end.date && result.end.time || !result.start.date && result.start.time && result.end.date && !result.end.time)) {
return false;
}
// both start and end cannot have month ambiguity
if (result.start && result.start._ambiguousMonth && result.end && result.end._ambiguousMonth) {
return false;
}
// if we've specified a time, we can't be allday
if (result.allDay && (!result.start._ambiguousTime || result.end && !result.end._ambiguousTime)) {
return false;
}
return true;
}
const Range = exports.Range = {
id: 'elliptical-datetime:Range',
defaultProps: {
prepositions: false,
seconds: true,
defaultTime: { hour: 8 },
defaultDuration: { hours: 1 },
future: true,
past: true,
label: 'period of time'
},
filterResult(result, { props }) {
const startMoment = (0, _moment2.default)(result.start);
const endMoment = (0, _moment2.default)(result.end);
if (endMoment.isBefore(startMoment)) return false;
const currentMoment = result.allDay ? (0, _moment2.default)().startOf('day') : (0, _moment2.default)();
if (!props.past && currentMoment.isAfter(startMoment)) return false;
if (!props.future && currentMoment.isBefore(endMoment)) return false;
return true;
},
describe({ props }) {
return (0, _elliptical.createElement)(
'placeholder',
{
label: props.label,
arguments: props.phraseArguments || (props.phraseArguments ? [props.phraseArgument] : [props.label]) },
(0, _elliptical.createElement)(
'map',
{ outbound: option => mapRangeOptions(option, props), limit: 1, skipIncomplete: true },
(0, _elliptical.createElement)(
'filter',
{ outbound: filterRangeOption, skipIncomplete: true },
(0, _elliptical.createElement)(
'sequence',
{ unique: true },
(0, _elliptical.createElement)(
'sequence',
{ id: 'duration', optional: true, limited: true },
props.prepositions ? (0, _elliptical.createElement)('literal', { text: 'for ', decorate: true }) : null,
(0, _elliptical.createElement)(_duration.Duration, { merge: true }),
(0, _elliptical.createElement)('list', { items: [' ', ' starting '], limit: 1 })
),
(0, _elliptical.createElement)(TrueDateTime, { ellipsis: true, id: 'start' }),
(0, _elliptical.createElement)(
'choice',
{ merge: true },
(0, _elliptical.createElement)(
'sequence',
{ id: 'end' },
(0, _elliptical.createElement)('list', { items: [' to ', ' - ', '-', '- ', ' -'], limit: 1 }),
(0, _elliptical.createElement)(TrueDateTime, { merge: true })
),
(0, _elliptical.createElement)(
'sequence',
{ id: 'duration' },
(0, _elliptical.createElement)('literal', { text: ' for ' }),
(0, _elliptical.createElement)(_duration.Duration, { merge: true })
)
)
)
)
)
);
}
};