Make util.scand a bit more flexible with dates which don't match the given format (bug 1910431)
This commit is contained in:
parent
bde36f28be
commit
230d7f9229
@ -38,7 +38,6 @@ class AForm {
|
|||||||
"m/d/yy HH:MM",
|
"m/d/yy HH:MM",
|
||||||
];
|
];
|
||||||
this._timeFormats = ["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"];
|
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:
|
// The e-mail address regex below originates from:
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
|
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
|
||||||
@ -53,120 +52,20 @@ class AForm {
|
|||||||
return event.target ? `[ ${event.target.name} ]` : "";
|
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) {
|
_parseDate(cFormat, cDate, strict = false) {
|
||||||
let date = null;
|
let date = null;
|
||||||
try {
|
try {
|
||||||
date = this._util.scand(cFormat, cDate);
|
date = this._util._scand(cFormat, cDate, strict);
|
||||||
} catch {}
|
} catch {}
|
||||||
if (!date) {
|
if (date) {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
if (strict) {
|
if (strict) {
|
||||||
return null;
|
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) {
|
|
||||||
date = Date.parse(cDate);
|
date = Date.parse(cDate);
|
||||||
date = isNaN(date)
|
return isNaN(date) ? null : new Date(date);
|
||||||
? this._tryToGuessDate(cFormat, cDate)
|
|
||||||
: new Date(date);
|
|
||||||
}
|
|
||||||
return date;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AFMergeChange(event = globalThis.event) {
|
AFMergeChange(event = globalThis.event) {
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
import { PDFObject } from "./pdf_object.js";
|
import { PDFObject } from "./pdf_object.js";
|
||||||
|
|
||||||
class Util extends PDFObject {
|
class Util extends PDFObject {
|
||||||
|
#dateActionsCache = null;
|
||||||
|
|
||||||
constructor(data) {
|
constructor(data) {
|
||||||
super(data);
|
super(data);
|
||||||
|
|
||||||
@ -338,7 +340,98 @@ class Util extends PDFObject {
|
|||||||
return buf.join("");
|
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) {
|
scand(cFormat, cDate) {
|
||||||
|
return this._scand(cFormat, cDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
_scand(cFormat, cDate, strict = false) {
|
||||||
if (typeof cDate !== "string") {
|
if (typeof cDate !== "string") {
|
||||||
return new Date(cDate);
|
return new Date(cDate);
|
||||||
}
|
}
|
||||||
@ -508,7 +601,7 @@ class Util extends PDFObject {
|
|||||||
|
|
||||||
const matches = new RegExp(`^${re}$`, "g").exec(cDate);
|
const matches = new RegExp(`^${re}$`, "g").exec(cDate);
|
||||||
if (!matches || matches.length !== actions.length + 1) {
|
if (!matches || matches.length !== actions.length + 1) {
|
||||||
return null;
|
return strict ? null : this.#tryToGuessDate(cFormat, cDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
|||||||
@ -243,6 +243,12 @@ describe("Scripting", function () {
|
|||||||
|
|
||||||
value = await myeval(`util.scand(2, "4/15/07 3:14:15 am").toString()`);
|
value = await myeval(`util.scand(2, "4/15/07 3:14:15 am").toString()`);
|
||||||
expect(new Date(value)).toEqual(date);
|
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"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user