Skip to content

Commit

Permalink
Merge pull request #18967 from calixteman/bug1910431
Browse files Browse the repository at this point in the history
Make util.scand a bit more flexible with dates which don't match the given format (bug 1910431)
  • Loading branch information
calixteman authored Oct 28, 2024
2 parents 5418060 + 230d7f9 commit 2bee3af
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 110 deletions.
117 changes: 8 additions & 109 deletions src/scripting_api/aform.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class AForm {
"m/d/yy HH:MM",
];
this._timeFormats = ["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"];
this._dateActionsCache = new Map();

// The e-mail address regex below originates from:
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
Expand All @@ -53,120 +52,20 @@ class AForm {
return event.target ? `[ ${event.target.name} ]` : "";
}

_tryToGuessDate(cFormat, cDate) {
// We use the format to know the order of day, month, year, ...

let actions = this._dateActionsCache.get(cFormat);
if (!actions) {
actions = [];
this._dateActionsCache.set(cFormat, actions);
cFormat.replaceAll(
/(d+)|(m+)|(y+)|(H+)|(M+)|(s+)/g,
function (match, d, m, y, H, M, s) {
if (d) {
actions.push((n, date) => {
if (n >= 1 && n <= 31) {
date.setDate(n);
return true;
}
return false;
});
} else if (m) {
actions.push((n, date) => {
if (n >= 1 && n <= 12) {
date.setMonth(n - 1);
return true;
}
return false;
});
} else if (y) {
actions.push((n, date) => {
if (n < 50) {
n += 2000;
} else if (n < 100) {
n += 1900;
}
date.setYear(n);
return true;
});
} else if (H) {
actions.push((n, date) => {
if (n >= 0 && n <= 23) {
date.setHours(n);
return true;
}
return false;
});
} else if (M) {
actions.push((n, date) => {
if (n >= 0 && n <= 59) {
date.setMinutes(n);
return true;
}
return false;
});
} else if (s) {
actions.push((n, date) => {
if (n >= 0 && n <= 59) {
date.setSeconds(n);
return true;
}
return false;
});
}
return "";
}
);
}

const number = /\d+/g;
let i = 0;
let array;
const date = new Date();
while ((array = number.exec(cDate)) !== null) {
if (i < actions.length) {
if (!actions[i++](parseInt(array[0]), date)) {
return null;
}
} else {
break;
}
}

if (i === 0) {
return null;
}

return date;
}

_parseDate(cFormat, cDate, strict = false) {
let date = null;
try {
date = this._util.scand(cFormat, cDate);
date = this._util._scand(cFormat, cDate, strict);
} catch {}
if (!date) {
if (strict) {
return null;
}
let format = cFormat;
if (/mm(?!m)/.test(format)) {
format = format.replace("mm", "m");
}
if (/dd(?!d)/.test(format)) {
format = format.replace("dd", "d");
}
try {
date = this._util.scand(format, cDate);
} catch {}
if (date) {
return date;
}
if (!date) {
date = Date.parse(cDate);
date = isNaN(date)
? this._tryToGuessDate(cFormat, cDate)
: new Date(date);
if (strict) {
return null;
}
return date;

date = Date.parse(cDate);
return isNaN(date) ? null : new Date(date);
}

AFMergeChange(event = globalThis.event) {
Expand Down
95 changes: 94 additions & 1 deletion src/scripting_api/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import { PDFObject } from "./pdf_object.js";

class Util extends PDFObject {
#dateActionsCache = null;

constructor(data) {
super(data);

Expand Down Expand Up @@ -338,7 +340,98 @@ class Util extends PDFObject {
return buf.join("");
}

#tryToGuessDate(cFormat, cDate) {
// We use the format to know the order of day, month, year, ...

let actions = (this.#dateActionsCache ||= new Map()).get(cFormat);
if (!actions) {
actions = [];
this.#dateActionsCache.set(cFormat, actions);
cFormat.replaceAll(
/(d+)|(m+)|(y+)|(H+)|(M+)|(s+)/g,
function (match, d, m, y, H, M, s) {
if (d) {
actions.push((n, date) => {
if (n >= 1 && n <= 31) {
date.setDate(n);
return true;
}
return false;
});
} else if (m) {
actions.push((n, date) => {
if (n >= 1 && n <= 12) {
date.setMonth(n - 1);
return true;
}
return false;
});
} else if (y) {
actions.push((n, date) => {
if (n < 50) {
n += 2000;
} else if (n < 100) {
n += 1900;
}
date.setYear(n);
return true;
});
} else if (H) {
actions.push((n, date) => {
if (n >= 0 && n <= 23) {
date.setHours(n);
return true;
}
return false;
});
} else if (M) {
actions.push((n, date) => {
if (n >= 0 && n <= 59) {
date.setMinutes(n);
return true;
}
return false;
});
} else if (s) {
actions.push((n, date) => {
if (n >= 0 && n <= 59) {
date.setSeconds(n);
return true;
}
return false;
});
}
return "";
}
);
}

const number = /\d+/g;
let i = 0;
let array;
const date = new Date(0);
while ((array = number.exec(cDate)) !== null) {
if (i < actions.length) {
if (!actions[i++](parseInt(array[0]), date)) {
return null;
}
} else {
break;
}
}

if (i === 0) {
return null;
}

return date;
}

scand(cFormat, cDate) {
return this._scand(cFormat, cDate);
}

_scand(cFormat, cDate, strict = false) {
if (typeof cDate !== "string") {
return new Date(cDate);
}
Expand Down Expand Up @@ -508,7 +601,7 @@ class Util extends PDFObject {

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

const data = {
Expand Down
6 changes: 6 additions & 0 deletions test/unit/scripting_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ describe("Scripting", function () {

value = await myeval(`util.scand(2, "4/15/07 3:14:15 am").toString()`);
expect(new Date(value)).toEqual(date);

value = await myeval(`util.scand("mmddyyyy", "07/15/2007").toString()`);
expect(new Date(value)).toEqual(new Date("07/15/2007"));

value = await myeval(`util.scand("mmddyyyy", "07a15b2007").toString()`);
expect(new Date(value)).toEqual(new Date("07/15/2007"));
});
});

Expand Down

0 comments on commit 2bee3af

Please sign in to comment.