UNPKG

chrono-node

Version:

A natural language date parser in Javascript

102 lines 4.17 kB
import { ReferenceWithTimezone, ParsingComponents, ParsingResult } from "./results.js"; import ENDefaultConfiguration from "./locales/en/configuration.js"; export class Chrono { constructor(configuration) { this.defaultConfig = new ENDefaultConfiguration(); configuration = configuration || this.defaultConfig.createCasualConfiguration(); this.parsers = [...configuration.parsers]; this.refiners = [...configuration.refiners]; } clone() { return new Chrono({ parsers: [...this.parsers], refiners: [...this.refiners], }); } parseDate(text, referenceDate, option) { const results = this.parse(text, referenceDate, option); return results.length > 0 ? results[0].start.date() : null; } parse(text, referenceDate, option) { const context = new ParsingContext(text, referenceDate, option); let results = []; this.parsers.forEach((parser) => { const parsedResults = Chrono.executeParser(context, parser); results = results.concat(parsedResults); }); results.sort((a, b) => { return a.index - b.index; }); this.refiners.forEach(function (refiner) { results = refiner.refine(context, results); }); return results; } static executeParser(context, parser) { const results = []; const pattern = parser.pattern(context); const originalText = context.text; let remainingText = context.text; let match = pattern.exec(remainingText); while (match) { const index = match.index + originalText.length - remainingText.length; match.index = index; const result = parser.extract(context, match); if (!result) { remainingText = originalText.substring(match.index + 1); match = pattern.exec(remainingText); continue; } let parsedResult = null; if (result instanceof ParsingResult) { parsedResult = result; } else if (result instanceof ParsingComponents) { parsedResult = context.createParsingResult(match.index, match[0]); parsedResult.start = result; } else { parsedResult = context.createParsingResult(match.index, match[0], result); } const parsedIndex = parsedResult.index; const parsedText = parsedResult.text; context.debug(() => console.log(`${parser.constructor.name} extracted (at index=${parsedIndex}) '${parsedText}'`)); results.push(parsedResult); remainingText = originalText.substring(parsedIndex + parsedText.length); match = pattern.exec(remainingText); } return results; } } export class ParsingContext { constructor(text, refDate, option) { this.text = text; this.reference = new ReferenceWithTimezone(refDate); this.option = option ?? {}; this.refDate = this.reference.instant; } createParsingComponents(components) { if (components instanceof ParsingComponents) { return components; } return new ParsingComponents(this.reference, components); } createParsingResult(index, textOrEndIndex, startComponents, endComponents) { const text = typeof textOrEndIndex === "string" ? textOrEndIndex : this.text.substring(index, textOrEndIndex); const start = startComponents ? this.createParsingComponents(startComponents) : null; const end = endComponents ? this.createParsingComponents(endComponents) : null; return new ParsingResult(this.reference, index, text, start, end); } debug(block) { if (this.option.debug) { if (this.option.debug instanceof Function) { this.option.debug(block); } else { const handler = this.option.debug; handler.debug(block); } } } } //# sourceMappingURL=chrono.js.map