(s, fmt)
| 41 | // Compile the format into a regex, capture fields, assemble a struct_time JSON. |
| 42 | const STRP = { Y: "(\\d{4})", y: "(\\d{2})", m: "(\\d{1,2})", d: "(\\d{1,2})", H: "(\\d{1,2})", M: "(\\d{1,2})", S: "(\\d{1,2})", j: "(\\d{1,3})", b: "([A-Za-z]+)", B: "([A-Za-z]+)", a: "([A-Za-z]+)", A: "([A-Za-z]+)" }; |
| 43 | const strptime = (s, fmt) => { |
| 44 | const fields = []; |
| 45 | const src = fmt.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/%(.)/g, (_, c) => { |
| 46 | if (c === "%") return "%"; |
| 47 | if (!(c in STRP)) return "%" + c; |
| 48 | fields.push(c); |
| 49 | return STRP[c]; |
| 50 | }); |
| 51 | const m = new RegExp("^" + src + "$").exec(s); |
| 52 | if (!m) throw new Error(`time data '${s}' does not match format '${fmt}'`); |
| 53 | let Y = 1900, mo = 1, d = 1, H = 0, Mi = 0, S = 0; |
| 54 | fields.forEach((f, i) => { |
| 55 | const v = m[i + 1]; |
| 56 | if (f === "Y") Y = +v; |
| 57 | else if (f === "y") Y = 2000 + +v; |
| 58 | else if (f === "m") mo = +v; |
| 59 | else if (f === "d") d = +v; |
| 60 | else if (f === "H") H = +v; |
| 61 | else if (f === "M") Mi = +v; |
| 62 | else if (f === "S") S = +v; |
| 63 | else if (f === "b" || f === "B") mo = monthIndex(v) + 1; |
| 64 | }); |
| 65 | return toTuple(new Date(Date.UTC(Y, mo - 1, d, H, Mi, S)), true); |
| 66 | }; |
| 67 | |
| 68 | export default () => ({ |
| 69 | gmtime: (secs) => toTuple(new Date((secs ?? Date.now() / 1000) * 1000), true), |
nothing calls this directly
no test coverage detected