@kermank/nldp
Version:
A modular date/time parser for converting natural language into dates and times
121 lines • 5.75 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.relativeWeeksRule = void 0;
const luxon_1 = require("luxon");
function createWeekComponent(start, end, span, originalText, preferences) {
// Use the timezone from preferences, or keep the original timezone if none specified
const targetZone = preferences.timeZone || (start.zoneName || 'UTC');
// Only convert if target timezone is different from current
let startResult = start.zoneName !== targetZone ? start.setZone(targetZone) : start;
let endResult = end.zoneName !== targetZone ? end.setZone(targetZone) : end;
return {
type: 'range',
span,
value: {
start: startResult,
end: endResult
},
confidence: 1,
metadata: {
originalText,
dateType: 'relative',
rangeType: 'relativeWeek'
}
};
}
function getWeekRange(date, weekStartsOn = 1, preferences) {
// First, ensure we're in the right timezone
const targetZone = preferences.timeZone || (date.zoneName || 'UTC');
const operationalDate = date.zoneName !== targetZone ? date.setZone(targetZone) : date;
// Convert weekStartsOn from 0-6 (Sunday=0) to 1-7 (Monday=1) for Luxon
const luxonWeekStart = weekStartsOn === 0 ? 7 : weekStartsOn;
// Use Luxon's built-in startOf('week') with the correct weekday
const start = operationalDate.set({ weekday: luxonWeekStart }).startOf('day');
const end = start.plus({ days: 6 }).endOf('day');
// If we're past the week start, move to next week
if (operationalDate.weekday < luxonWeekStart) {
return { start: start.minus({ weeks: 1 }), end: end.minus({ weeks: 1 }) };
}
return { start, end };
}
function getNextWeekRange(date, weekStartsOn = 1, preferences) {
const { start } = getWeekRange(date, weekStartsOn, preferences);
// Simply add 7 days to both start and end of current week
const nextStart = start.plus({ weeks: 1 });
const nextEnd = nextStart.plus({ days: 6 }).endOf('day');
return { start: nextStart, end: nextEnd };
}
function getLastWeekRange(date, weekStartsOn = 1, preferences) {
const { start } = getWeekRange(date, weekStartsOn, preferences);
// Simply subtract 7 days from both start and end of current week
const lastStart = start.minus({ weeks: 1 });
const lastEnd = lastStart.plus({ days: 6 }).endOf('day');
return { start: lastStart, end: lastEnd };
}
const patterns = [
{
regex: /(?:^|\s)(this|next|last)\s+week(?:\s+|$)/i,
parse: (matches, preferences) => {
const [fullMatch, weekModifier] = matches;
const referenceDate = preferences.referenceDate || luxon_1.DateTime.now();
const weekStartsOn = preferences.weekStartsOn;
let range;
switch (weekModifier.toLowerCase()) {
case 'next':
range = getNextWeekRange(referenceDate, weekStartsOn, preferences);
break;
case 'last':
range = getLastWeekRange(referenceDate, weekStartsOn, preferences);
break;
default:
range = getWeekRange(referenceDate, weekStartsOn, preferences);
}
const matchStart = matches.index + (fullMatch.startsWith(' ') ? 1 : 0);
const matchEnd = matchStart + fullMatch.trim().length;
return createWeekComponent(range.start, range.end, { start: matchStart, end: matchEnd }, fullMatch.trim(), preferences);
}
},
{
regex: /^(the\s+)?week\s+after\s+next$/i,
parse: (matches, preferences) => {
const [fullMatch] = matches;
const referenceDate = preferences.referenceDate || luxon_1.DateTime.now();
const weekStartsOn = preferences.weekStartsOn;
const nextWeek = getNextWeekRange(referenceDate, weekStartsOn, preferences);
const weekAfterNext = getNextWeekRange(nextWeek.start, weekStartsOn, preferences);
return createWeekComponent(weekAfterNext.start, weekAfterNext.end, { start: 0, end: fullMatch.length }, fullMatch, preferences);
}
},
{
regex: /^(\d+)\s+weeks?\s+(from\s+now|ago)$/i,
parse: (matches, preferences) => {
const [fullMatch, count, direction] = matches;
const weeks = parseInt(count);
if (isNaN(weeks))
return null;
const referenceDate = preferences.referenceDate || luxon_1.DateTime.now();
const weekStartsOn = preferences.weekStartsOn;
const currentWeek = getWeekRange(referenceDate, weekStartsOn, preferences);
const targetDate = direction.includes('ago')
? currentWeek.start.minus({ days: weeks * 7 })
: currentWeek.start.plus({ days: weeks * 7 });
const range = getWeekRange(targetDate, weekStartsOn, preferences);
return createWeekComponent(range.start, range.end, { start: 0, end: fullMatch.length }, fullMatch, preferences);
}
},
{
regex: /^upcoming\s+week$/i,
parse: (matches, preferences) => {
const [fullMatch] = matches;
const referenceDate = preferences.referenceDate || luxon_1.DateTime.now();
const weekStartsOn = preferences.weekStartsOn;
const range = getNextWeekRange(referenceDate, weekStartsOn, preferences);
return createWeekComponent(range.start, range.end, { start: 0, end: fullMatch.length }, fullMatch, preferences);
}
}
];
exports.relativeWeeksRule = {
name: 'relative-weeks',
patterns
};
//# sourceMappingURL=relative-weeks.js.map