Last active
March 1, 2023 20:09
-
-
Save tjjfvi/80d1379437e9192379c6e81b7396c2bc to your computer and use it in GitHub Desktop.
A regex matching only ISO8601-formatted dates representing weekdays
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @ts-nocheck | |
const charset = [..."0123456789-"]; | |
let visitState, | |
x, | |
obj, | |
selfPath, | |
initialPath, | |
path; | |
const str = JSON.stringify; | |
const initial = 0; | |
const accept = 1; | |
const next = 2; | |
const testDfa = (dfa, i) => | |
dfa[accept]([...i].reduce((a, b) => dfa[next](a)(b), dfa[initial])); | |
const dfaToString = (dfa, paths = { s: { [str(dfa[initial])]: "" } }) => ( | |
(visitState = (state) => | |
paths[x = str(state)] = paths[x] || | |
(paths[x] = {}, | |
charset.reduce((obj, char, nextState) => ( | |
nextState = dfa[next](state)(char), | |
visitState(nextState), | |
obj[x = str(nextState)] = (obj[x] || "[]").slice(0, -1) + | |
(char == "\\" || char == "]" ? "\\" : "") + char + "]", | |
dfa[accept](state) && (obj.e = ""), | |
obj | |
), {})))(dfa[initial]), | |
Object.keys(paths).map((removeState) => | |
removeState != "s" && ( | |
obj = paths[removeState], | |
selfPath = obj[removeState], | |
delete obj[removeState], | |
delete paths[removeState], | |
Object.keys(paths).map((a) => | |
( | |
initialPath = paths[a][removeState] | |
) !== {}.x && | |
delete paths[a][removeState] && | |
Object.keys(obj).map((b) => ( | |
path = initialPath + (selfPath ? `(${selfPath})*` : "") + obj[b], | |
paths[a][b] = paths[a][b] != {}.x | |
? `(?:${paths[a][b]}|${path})` | |
: path | |
)) | |
) | |
) | |
), | |
paths.s.e || "[]" | |
); | |
const mlts = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; | |
const mltslp = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; | |
const weekday = [ | |
[0, 0, 4, 0], | |
(state) => !!(state && state[2] < 5), | |
(state) => (char) => { | |
if (!state) return null; | |
let [i, lp, dm7, c] = state; | |
if (i === 10) return null; | |
if (char === "-") { | |
return i === 4 || i === 7 ? [i + 1, lp, dm7, c] : null; | |
} | |
if (i === 4 || i === 7) return null; | |
if (i === 0 || i === 2) { | |
return [i + 1, lp, dm7, +char]; | |
} | |
if (i === 1) { | |
let cy = c * 10 + +char; | |
return [i + 1, cy % 4, dm7, 0]; | |
} | |
if (i === 3) { | |
let y = c * 10 + +char; | |
let le = +(y % 4 === 0 && (y !== 0 || lp === 0)); | |
return [ | |
i + 1, | |
le, | |
(dm7 + lp * 5 + y + ((y - 1) / 4 | 0) + +!(lp === 0 && y === 0)) % 7, | |
0, | |
]; | |
} | |
if (i === 5) { | |
if (char !== "0" && char !== "1") return null; | |
return [i + 1, lp, dm7, +char]; | |
} | |
if (i === 6) { | |
let m = c * 10 + +char; | |
if (m < 1 || m > 12) return null; | |
let mls = lp ? mltslp : mlts; | |
return [ | |
i + 1, | |
mls[m - 1], | |
(dm7 + mls.slice(0, m - 1).reduce((a, b) => a + b, 0)) % 7, | |
0, | |
]; | |
} | |
if (i === 8) { | |
if (+char > 3) return null; | |
return [i + 1, lp, dm7, +char]; | |
} | |
if (i === 9) { | |
let d = c * 10 + +char; | |
if (d < 1 || d > lp) return null; | |
return [i + 1, 0, (dm7 + d) % 7, 0]; | |
} | |
}, | |
]; | |
const regexSource = `^${dfaToString(weekday)}$`; | |
Deno.writeTextFile("weekday-regex", `/${regexSource}/`); | |
const rgx = new RegExp(regexSource); | |
const trues = [ | |
"2023-02-27", | |
"2023-02-28", | |
"2023-03-01", | |
"2023-03-02", | |
"2023-03-03", | |
"2023-03-06", | |
"2023-03-07", | |
"1940-07-12", | |
"1927-02-23", | |
"1928-02-23", | |
]; | |
console.log("true:"); | |
for (const x of trues) console.log(x, test(x)); | |
console.log("\nfalse:"); | |
const falses = [ | |
"2023-02-26", | |
"2023-03-04", | |
"2023-03-05", | |
"2023-02-29", | |
"2023-12-90", | |
"2020-20-20", | |
"2023-2-27", | |
"2023-2-2", | |
"----------", | |
"0001-01-01", | |
"1940-07-13", | |
"1927-02-26", | |
"1929-02-23", | |
]; | |
for (const x of falses) console.log(x, test(x)); | |
function test(x) { | |
// return rgx.test(x); | |
return testDfa(weekday, x); | |
} |
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment