UNPKG

chrono-node

Version:

A natural language date parser in Javascript

73 lines (60 loc) 3.07 kB
// Map ABBR -> Offset in minute import { ParsingContext, Refiner } from "../../chrono"; import { TimezoneAbbrMap } from "../../types"; import { ParsingResult } from "../../results"; import { toTimezoneOffset } from "../../timezone"; const TIMEZONE_NAME_PATTERN = new RegExp("^\\s*,?\\s*\\(?([A-Z]{2,4})\\)?(?=\\W|$)", "i"); export default class ExtractTimezoneAbbrRefiner implements Refiner { constructor(private readonly timezoneOverrides?: TimezoneAbbrMap) {} refine(context: ParsingContext, results: ParsingResult[]): ParsingResult[] { const timezoneOverrides = context.option.timezones ?? {}; results.forEach((result) => { const suffix = context.text.substring(result.index + result.text.length); const match = TIMEZONE_NAME_PATTERN.exec(suffix); if (!match) { return; } const timezoneAbbr = match[1].toUpperCase(); const refDate = result.start.date() ?? result.refDate ?? new Date(); const tzOverrides = { ...this.timezoneOverrides, ...timezoneOverrides }; const extractedTimezoneOffset = toTimezoneOffset(timezoneAbbr, refDate, tzOverrides); if (extractedTimezoneOffset == null) { return; } context.debug(() => { console.log( `Extracting timezone: '${timezoneAbbr}' into: ${extractedTimezoneOffset} for: ${result.start}` ); }); const currentTimezoneOffset = result.start.get("timezoneOffset"); if (currentTimezoneOffset !== null && extractedTimezoneOffset != currentTimezoneOffset) { // We may already have extracted the timezone offset e.g. "11 am GMT+0900 (JST)" // - if they are equal, we also want to take the abbreviation text into result // - if they are not equal, we trust the offset more if (result.start.isCertain("timezoneOffset")) { return; } // This is often because it's relative time with inferred timezone (e.g. in 1 hour, tomorrow) // Then, we want to double-check the abbr case (e.g. "GET" not "get") if (timezoneAbbr != match[1]) { return; } } if (result.start.isOnlyDate()) { // If the time is not explicitly mentioned, // Then, we also want to double-check the abbr case (e.g. "GET" not "get") if (timezoneAbbr != match[1]) { return; } } result.text += match[0]; if (!result.start.isCertain("timezoneOffset")) { result.start.assign("timezoneOffset", extractedTimezoneOffset); } if (result.end != null && !result.end.isCertain("timezoneOffset")) { result.end.assign("timezoneOffset", extractedTimezoneOffset); } }); return results; } }