elliptical-datetime
Version:
Elliptical phrases to handle natural language dates and times
279 lines (247 loc) • 10 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.InternalDateTime = exports.DateTime = 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 _elliptical = require('elliptical');
var _time = require('./time');
var _moment = require('moment');
var _moment2 = _interopRequireDefault(_moment);
var _helpers = require('./helpers');
var _date = require('./date');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function isNoonOrMidnight(time) {
return (time.hour === 12 || time.hour === 0) && !time.minute && !time.second;
}
function timeIsInAMPM(time, ampm) {
if (ampm === 'am') {
return time.hour >= 0 && time.hour < 12;
} else if (ampm === 'pm') {
return time.hour >= 12 && time.hour < 24;
}
}
const TrueDate = {
describe({ props }) {
return (0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)(
'choice',
{ merge: true },
(0, _elliptical.createElement)(_date.InternalDate, _extends({}, props, { id: undefined })),
(0, _elliptical.createElement)(
'map',
{ 'function': result => ({ date: result }), skipIncomplete: true },
(0, _elliptical.createElement)(_date.Date, _extends({}, props, { nullify: true }))
)
)
);
}
};
function* getDateTimeResults(result, props) {
let dates;
if (result.date) {
if (result._ambiguousWeek) {
dates = _lodash2.default.map([0, 1, -1], weeks => (0, _moment2.default)(result.date).add(weeks, 'weeks').toDate());
} else if (result._ambiguousCentury) {
dates = _lodash2.default.map([0, 100, -100], years => (0, _moment2.default)(result.date).add(years, 'years').toDate());
} else if (result._ambiguousYear) {
if (result._ambiguousMonth) {
dates = _lodash2.default.flatMap([0, 1, -1], y => {
return _lodash2.default.map([0, 1, -1], m => {
return (0, _moment2.default)(result.date).add(y, 'years').add(m, 'months').toDate();
});
});
} else {
dates = _lodash2.default.map([0, 1, -1], years => (0, _moment2.default)(result.date).add(years, 'years').toDate());
}
} else {
dates = [result.date];
}
} else {
dates = [undefined];
}
for (let date of dates) {
if (date && result.time) {
yield (0, _helpers.join)(date, result.time, props.timezoneOffset);
} else if (result.time && result.relativeDate) {
yield (0, _helpers.join)((0, _helpers.relativeDate)(result.relativeDate), result.time, props.timezoneOffset);
} else if (date) {
yield (0, _helpers.join)(date, props.defaultTime, props.timezoneOffset);
} else if (result.time) {
for (let i of [0, 1, -1]) {
yield (0, _helpers.join)((0, _helpers.relativeDate)({ days: i }), result.time, props.timezoneOffset);
}
}
}
}
function* getDateTimeOptions(option, props) {
for (let result of getDateTimeResults(option.result, props)) {
yield _lodash2.default.assign({}, option, { result });
}
}
// function filterDateTimeResult (result) {
// return true
// }
const DateTime = exports.DateTime = {
id: 'elliptical-datetime:DateTime',
defaultProps: {
defaultTime: { hour: 8, minute: 0, second: 0 },
past: true,
future: true,
prepositions: false,
label: 'date and time'
},
filterResult(result, { props }) {
if (!props.past && (0, _moment2.default)().isAfter(result)) {
return false;
}
if (!props.future && (0, _moment2.default)().isBefore(result)) {
return false;
}
return true;
},
describe({ props }) {
return props.nullify ? null : (0, _elliptical.createElement)(
'map',
{ outbound: option => getDateTimeOptions(option, props), limit: 1, skipIncomplete: true },
(0, _elliptical.createElement)(InternalDateTime, props)
);
}
};
function filterInternalDateTime(option) {
const result = option.result;
/*if (option.result.time && option.result.time._ambiguousAMPM &&
!option.result.timeOfDay) {
return false
} else */if (result.time && result.timeOfDay && isNoonOrMidnight(result.time)) {
return false;
} else if (result.time && result.timeOfDay && !result.time._ambiguousAMPM && !timeIsInAMPM(result.time, result.timeOfDay.impliedAMPM)) {
return false;
}
return true;
}
const InternalDateTime = exports.InternalDateTime = {
defaultProps: {
label: 'date and time'
},
mapResult(result) {
let time = result.time;
if (result.timeOfDay && result.time && result.time._ambiguousAMPM) {
time = (0, _helpers.ambiguousTime)(result.time, result.timeOfDay.impliedAMPM);
} else if (result.timeOfDay && !result.time) {
time = { hour: result.timeOfDay.default };
}
let date = result.date && result.date.date;
if (result.relativeDate) {
date = (0, _helpers.relativeDate)(result.relativeDate);
}
// console.log(result)
return {
date,
time,
_ambiguousYear: result.date && result.date._ambiguousYear,
_ambiguousCentury: result.date && result.date._ambiguousCentury,
_ambiguousWeek: result.date && result.date._ambiguousWeek,
_ambiguousMonth: result.date && result.date._ambiguousMonth,
_ambiguousAMPM: result.time && result.time._ambiguousAMPM,
_specificAMPM: result.time && result.time._specificAMPM
};
},
describe({ props }) {
return (0, _elliptical.createElement)(
'placeholder',
{
label: props.label,
arguments: props.phraseArguments || (props.phraseArguments ? [props.phraseArgument] : [props.label]) },
(0, _elliptical.createElement)(
'filter',
{ outbound: filterInternalDateTime, skipIncomplete: true },
(0, _elliptical.createElement)(
'choice',
null,
(0, _elliptical.createElement)(
'sequence',
{ unique: true },
(0, _elliptical.createElement)(
'sequence',
{ merge: true },
(0, _elliptical.createElement)(_time.InternalTime, { id: 'time', ellipsis: true, prepositions: props.prepositions, seconds: false }),
(0, _elliptical.createElement)(
'sequence',
{ optional: true, limited: true, ellipsis: true, merge: true },
(0, _elliptical.createElement)(
'sequence',
{ id: 'timeOfDay', optional: true, limited: true },
(0, _elliptical.createElement)('literal', { text: ' the ' }),
(0, _elliptical.createElement)(_time.TimeOfDay, { merge: true }),
(0, _elliptical.createElement)('literal', { text: ' of' })
),
(0, _elliptical.createElement)(
'sequence',
{ id: 'date' },
(0, _elliptical.createElement)('literal', { text: ' ' }),
(0, _elliptical.createElement)(TrueDate, { merge: true, prepositions: true })
)
),
(0, _elliptical.createElement)(
'sequence',
{ id: 'timeOfDay' },
(0, _elliptical.createElement)('list', { items: [' ', ' in the '], limit: 1 }),
(0, _elliptical.createElement)(_time.TimeOfDay, { merge: true })
)
)
),
(0, _elliptical.createElement)(
'sequence',
{ unique: true },
(0, _elliptical.createElement)(
'sequence',
{ id: 'timeOfDay', optional: true, limited: true },
(0, _elliptical.createElement)('literal', { text: 'the ' }),
(0, _elliptical.createElement)(_time.TimeOfDay, { merge: true }),
(0, _elliptical.createElement)('literal', { text: ' of ' })
),
(0, _elliptical.createElement)(
'choice',
{ merge: true, ellipsis: true },
(0, _elliptical.createElement)(TrueDate, { id: 'date', prepositions: props.prepositions }),
(0, _elliptical.createElement)(
'sequence',
null,
(0, _elliptical.createElement)('literal', { id: 'relativeDate', text: 'this ', value: { day: 0 } }),
(0, _elliptical.createElement)(_time.TimeOfDay, { id: 'timeOfDay' })
),
(0, _elliptical.createElement)(
'placeholder',
{ label: 'date' },
(0, _elliptical.createElement)('literal', { text: 'tonight', value: { relativeDate: { day: 0 }, time: { hour: 20 } } })
)
),
(0, _elliptical.createElement)(
'sequence',
{ id: 'timeOfDay', optional: true, limited: true, ellipsis: true },
(0, _elliptical.createElement)('list', { items: [' ', ' in the '], limit: 1 }),
(0, _elliptical.createElement)(_time.TimeOfDay, { merge: true })
),
(0, _elliptical.createElement)(
'sequence',
{ id: 'time', ellipsis: true },
(0, _elliptical.createElement)('literal', { text: ' ' }),
(0, _elliptical.createElement)(_time.InternalTime, { merge: true, prepositions: true, seconds: false })
),
(0, _elliptical.createElement)(
'sequence',
{ id: 'timeOfDay' },
(0, _elliptical.createElement)('literal', { text: ' in the ' }),
(0, _elliptical.createElement)(_time.TimeOfDay, { merge: true })
)
)
)
)
);
}
};