Merge pull request #15493 from calixteman/15490

[JS] Try to guess what the date is when it doesn't follow the given format (issue #15490)
This commit is contained in:
calixteman 2022-09-22 16:54:33 +02:00 committed by GitHub
commit 9bdcdeef67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 100 additions and 3 deletions

View File

@ -38,6 +38,7 @@ 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
@ -52,6 +53,93 @@ 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.replace(
/(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) {
let date = null;
try {
@ -60,7 +148,7 @@ class AForm {
if (!date) {
date = Date.parse(cDate);
if (isNaN(date)) {
date = null;
date = this._tryToGuessDate(cFormat, cDate);
} else {
date = new Date(date);
}

View File

@ -608,14 +608,23 @@ describe("Scripting", function () {
it("should parse a date with a format", async () => {
const check = async (date, format, expected) => {
const value = await myeval(
`AFParseDateEx("${date}", "${format}").toISOString()`
`AFParseDateEx("${date}", "${format}").toISOString().replace(/T.*$/, "")`
);
expect(value).toEqual(
new Date(expected).toISOString().replace(/T.*$/, "")
);
expect(value).toEqual(new Date(expected).toISOString());
};
await check("05", "dd", "2000/01/05");
await check("12", "mm", "2000/12/01");
await check("2022", "yyyy", "2022/01/01");
await check("a1$9bbbb21", "dd/mm/yyyy", "2021/09/01");
// The following test isn't working as expected because
// the quickjs date parser has been replaced by the browser one
// and the date "1.9.2021" is valid in Chrome but not in Firefox.
// The supported date format is not specified...
// await check("1.9.2021", "dd/mm/yyyy", "2021/09/01");
});
});