Skip to content

Commit

Permalink
New: Support reference following a date
Browse files Browse the repository at this point in the history
  • Loading branch information
Wanasit Tanakitrungruang committed Dec 30, 2023
1 parent f00e9ef commit fed9f9d
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 6 deletions.
11 changes: 9 additions & 2 deletions src/locales/en/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import ENRelativeDateFormatParser from "./parsers/ENRelativeDateFormatParser";

import SlashDateFormatParser from "../../common/parsers/SlashDateFormatParser";
import ENTimeUnitCasualRelativeFormatParser from "./parsers/ENTimeUnitCasualRelativeFormatParser";
import ENMergeRelativeDateRefiner from "./refiners/ENMergeRelativeDateRefiner";
import ENMergeRelativeAfterDateRefiner from "./refiners/ENMergeRelativeAfterDateRefiner";
import ENMergeRelativeFollowByDateRefiner from "./refiners/ENMergeRelativeFollowByDateRefiner";
import OverlapRemovalRefiner from "../../common/refiners/OverlapRemovalRefiner";

export default class ENDefaultConfiguration {
/**
Expand Down Expand Up @@ -58,10 +60,15 @@ export default class ENDefaultConfiguration {
new ENTimeUnitAgoFormatParser(strictMode),
new ENTimeUnitLaterFormatParser(strictMode),
],
refiners: [new ENMergeRelativeDateRefiner(), new ENMergeDateTimeRefiner()],
refiners: [new ENMergeDateTimeRefiner()],
},
strictMode
);
// These relative-dates consideration should be done before other common refiners.
options.refiners.unshift(new ENMergeRelativeFollowByDateRefiner());
options.refiners.unshift(new ENMergeRelativeAfterDateRefiner());
options.refiners.unshift(new OverlapRemovalRefiner());

// Re-apply the date time refiner again after the timezone refinement and exclusion in common refiners.
options.refiners.push(new ENMergeDateTimeRefiner());
// Keep the date range refiner at the end (after all other refinements).
Expand Down
46 changes: 46 additions & 0 deletions src/locales/en/refiners/ENMergeRelativeAfterDateRefiner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { MergingRefiner } from "../../../common/abstractRefiners";
import { ParsingComponents, ParsingResult, ReferenceWithTimezone } from "../../../results";
import { parseTimeUnits } from "../constants";
import { reverseTimeUnits } from "../../../utils/timeunits";

function IsPositiveFollowingReference(result: ParsingResult): boolean {
return result.text.match(/^[+-]/i) != null;
}

function IsNegativeFollowingReference(result: ParsingResult): boolean {
return result.text.match(/^-/i) != null;
}

/**
* Merges a relative data/time that comes after an absolute date.
* - [2020-02-13] [+2 weeks]
* - [next tuesday] [+10 days]
*/
export default class ENMergeRelativeAfterDateRefiner extends MergingRefiner {
shouldMergeResults(textBetween: string, currentResult: ParsingResult, nextResult: ParsingResult): boolean {
if (!textBetween.match(/^\s*$/i)) {
return false;
}

return IsPositiveFollowingReference(nextResult) || IsNegativeFollowingReference(nextResult);
}

mergeResults(textBetween: string, currentResult: ParsingResult, nextResult: ParsingResult, context): ParsingResult {
let timeUnits = parseTimeUnits(nextResult.text);
if (IsNegativeFollowingReference(nextResult)) {
timeUnits = reverseTimeUnits(timeUnits);
}

const components = ParsingComponents.createRelativeFromReference(
new ReferenceWithTimezone(currentResult.start.date()),
timeUnits
);

return new ParsingResult(
currentResult.reference,
currentResult.index,
`${currentResult.text}${textBetween}${nextResult.text}`,
components
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ function hasImpliedLaterReferenceDate(result: ParsingResult): boolean {
}

/**
* Merges an absolute date with a relative date.
* - 2 weeks before 2020-02-13
* - 2 days after next Friday
* Merges a relative data/time that follow by an absolute date.
* - [2 weeks before] [2020-02-13]
* - [2 days after] [next Friday]
*/
export default class ENMergeRelativeDateRefiner extends MergingRefiner {
export default class ENMergeRelativeFollowByDateRefiner extends MergingRefiner {
patternBetween(): RegExp {
return /^\s*$/i;
}
Expand Down
22 changes: 22 additions & 0 deletions test/en/en_time_units_later.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,25 @@ test("Test - After with reference", () => {
expect(result.start.get("day")).toBe(18);
});
});

test("Test - Plus after reference", () => {
testSingleCase(chrono, "next tuesday +10 days", new Date(2023, 12 - 1, 29), (result) => {
expect(result.start.get("year")).toBe(2024);
expect(result.start.get("month")).toBe(1);
expect(result.start.get("day")).toBe(12);
});

testSingleCase(chrono, "2023-12-29 -10days", new Date(2023, 12 - 1, 29), (result) => {
expect(result.start.get("year")).toBe(2023);
expect(result.start.get("month")).toBe(12);
expect(result.start.get("day")).toBe(19);
});

testSingleCase(chrono, "now + 40minutes", new Date(2023, 12 - 1, 29, 8, 30), (result) => {
expect(result.start.get("year")).toBe(2023);
expect(result.start.get("month")).toBe(12);
expect(result.start.get("day")).toBe(29);
expect(result.start.get("hour")).toBe(9);
expect(result.start.get("minute")).toBe(10);
});
});

0 comments on commit fed9f9d

Please sign in to comment.