_scand()

in src/scripting_api/util.js [448:643]


  _scand(cFormat, cDate, strict = false) {
    if (typeof cDate !== "string") {
      return new Date(cDate);
    }

    if (cDate === "") {
      return new Date();
    }

    switch (cFormat) {
      case 0:
        return this.scand("D:yyyymmddHHMMss", cDate);
      case 1:
        return this.scand("yyyy.mm.dd HH:MM:ss", cDate);
      case 2:
        return this.scand("m/d/yy h:MM:ss tt", cDate);
    }

    if (!this._scandCache.has(cFormat)) {
      const months = this._months;
      const days = this._days;

      const handlers = {
        mmmm: {
          pattern: `(${months.join("|")})`,
          action: (value, data) => {
            data.month = months.indexOf(value);
          },
        },
        mmm: {
          pattern: `(${months.map(month => month.substring(0, 3)).join("|")})`,
          action: (value, data) => {
            data.month = months.findIndex(
              month => month.substring(0, 3) === value
            );
          },
        },
        mm: {
          pattern: `(\\d{2})`,
          action: (value, data) => {
            data.month = parseInt(value) - 1;
          },
        },
        m: {
          pattern: `(\\d{1,2})`,
          action: (value, data) => {
            data.month = parseInt(value) - 1;
          },
        },
        dddd: {
          pattern: `(${days.join("|")})`,
          action: (value, data) => {
            data.day = days.indexOf(value);
          },
        },
        ddd: {
          pattern: `(${days.map(day => day.substring(0, 3)).join("|")})`,
          action: (value, data) => {
            data.day = days.findIndex(day => day.substring(0, 3) === value);
          },
        },
        dd: {
          pattern: "(\\d{2})",
          action: (value, data) => {
            data.day = parseInt(value);
          },
        },
        d: {
          pattern: "(\\d{1,2})",
          action: (value, data) => {
            data.day = parseInt(value);
          },
        },
        yyyy: {
          pattern: "(\\d{4})",
          action: (value, data) => {
            data.year = parseInt(value);
          },
        },
        yy: {
          pattern: "(\\d{2})",
          action: (value, data) => {
            data.year = 2000 + parseInt(value);
          },
        },
        HH: {
          pattern: "(\\d{2})",
          action: (value, data) => {
            data.hours = parseInt(value);
          },
        },
        H: {
          pattern: "(\\d{1,2})",
          action: (value, data) => {
            data.hours = parseInt(value);
          },
        },
        hh: {
          pattern: "(\\d{2})",
          action: (value, data) => {
            data.hours = parseInt(value);
          },
        },
        h: {
          pattern: "(\\d{1,2})",
          action: (value, data) => {
            data.hours = parseInt(value);
          },
        },
        MM: {
          pattern: "(\\d{2})",
          action: (value, data) => {
            data.minutes = parseInt(value);
          },
        },
        M: {
          pattern: "(\\d{1,2})",
          action: (value, data) => {
            data.minutes = parseInt(value);
          },
        },
        ss: {
          pattern: "(\\d{2})",
          action: (value, data) => {
            data.seconds = parseInt(value);
          },
        },
        s: {
          pattern: "(\\d{1,2})",
          action: (value, data) => {
            data.seconds = parseInt(value);
          },
        },
        tt: {
          pattern: "([aApP][mM])",
          action: (value, data) => {
            const char = value.charAt(0);
            data.am = char === "a" || char === "A";
          },
        },
        t: {
          pattern: "([aApP])",
          action: (value, data) => {
            data.am = value === "a" || value === "A";
          },
        },
      };

      // escape the string
      const escapedFormat = cFormat.replaceAll(/[.*+\-?^${}()|[\]\\]/g, "\\$&");
      const patterns =
        /(mmmm|mmm|mm|m|dddd|ddd|dd|d|yyyy|yy|HH|H|hh|h|MM|M|ss|s|tt|t)/g;
      const actions = [];

      const re = escapedFormat.replaceAll(
        patterns,
        function (match, patternElement) {
          const { pattern, action } = handlers[patternElement];
          actions.push(action);
          return pattern;
        }
      );

      this._scandCache.set(cFormat, [re, actions]);
    }

    const [re, actions] = this._scandCache.get(cFormat);

    const matches = new RegExp(`^${re}$`, "g").exec(cDate);
    if (!matches || matches.length !== actions.length + 1) {
      return strict ? null : this.#tryToGuessDate(cFormat, cDate);
    }

    const data = {
      year: new Date().getFullYear(),
      month: 0,
      day: 1,
      hours: 12,
      minutes: 0,
      seconds: 0,
      am: null,
    };
    actions.forEach((action, i) => action(matches[i + 1], data));
    if (data.am !== null) {
      data.hours = (data.hours % 12) + (data.am ? 0 : 12);
    }

    return new Date(
      data.year,
      data.month,
      data.day,
      data.hours,
      data.minutes,
      data.seconds
    );
  }