Last active
June 27, 2025 18:03
-
-
Save ggorlen/53a1262bfaf95ebaf5b376c3fc8ac7f8 to your computer and use it in GitHub Desktop.
Testing Chrono Node in the browser
This file contains hidden or 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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<meta name="color-scheme" content="dark light" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>chrono-node & Date Test</title> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.js"></script> | |
<style> | |
* { | |
font-family: monospace; | |
} | |
body { | |
margin: 1.5em; | |
} | |
.output { | |
margin-top: 1em; | |
} | |
table { | |
border-collapse: collapse; | |
margin-top: 1em; | |
} | |
th, td { | |
padding: 0.5em; | |
border: 1px solid #888; | |
} | |
code { | |
padding: 0.1em 0.3em; | |
border-radius: 4px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Date Tester</h1> | |
<input | |
id="dateInput" | |
value="today" | |
placeholder="Type a date expression..." | |
style="width: 100%; padding: 0.5em; font-size: 1em; max-width: 600px" | |
/> | |
<div class="output"> | |
<h3>chrono-node (2.4.1)</h3> | |
<div id="esm241Output"></div> | |
<div id="esm241OutputUTC"></div> | |
</div> | |
<div class="output"> | |
<h3>Vanilla JS <code>Date</code> parse</h3> | |
<div id="jsOutput"></div> | |
</div> | |
<div class="output"> | |
<h3>Static Test Dates</h3> | |
<table> | |
<thead> | |
<tr> | |
<th>Input</th> | |
<th>chrono 2.4.1 (local)</th> | |
<th>chrono 2.4.1 (UTC)</th> | |
<th>JS Date</th> | |
</tr> | |
</thead> | |
<tbody id="testTable"></tbody> | |
</table> | |
</div> | |
<div class="output"> | |
<h3>Luxon Test Dates</h3> | |
<table> | |
<thead> | |
<tr> | |
<th>Input</th> | |
<th>Luxon <code>fromFormat</code></th> | |
<th>Luxon ISO</th> | |
</tr> | |
</thead> | |
<tbody id="luxonTable"></tbody> | |
</table> | |
</div> | |
<div class="output"> | |
<h3>Environment Metrics</h3> | |
<ul> | |
<li><strong>User Agent:</strong> <span id="ua"></span></li> | |
<li><strong>System Date:</strong> <span id="sysDate"></span></li> | |
<li><strong>Intl Locale:</strong> <span id="locale"></span></li> | |
<li><strong>Time Zone:</strong> <span id="timezone"></span></li> | |
</ul> | |
</div> | |
<div class="luxon-out"></div> | |
<script> | |
document.getElementById("ua").textContent = navigator.userAgent; | |
const now = new Date(); | |
document.getElementById("sysDate").textContent = `${now.toString()} (Local) / ${now.toISOString()} (UTC)`; | |
document.getElementById("locale").textContent = Intl.DateTimeFormat().resolvedOptions().locale; | |
document.getElementById("timezone").textContent = Intl.DateTimeFormat().resolvedOptions().timeZone; | |
</script> | |
<script type="module"> | |
import * as chrono241 from "https://esm.sh/[email protected]"; | |
const input = document.getElementById("dateInput"); | |
const esm241Output = document.getElementById("esm241Output"); | |
const esm241OutputUTC = document.getElementById("esm241OutputUTC"); | |
const jsOutput = document.getElementById("jsOutput"); | |
function update(text) { | |
let chronoDate; | |
try { | |
chronoDate = chrono241.parseDate(text); | |
} catch (e) { | |
chronoDate = null; | |
} | |
if (chronoDate) { | |
esm241Output.textContent = `Local ISO: ${chronoDate.toISOString()}`; | |
esm241OutputUTC.textContent = `UTC ISO: ${luxon.DateTime.fromJSDate(chronoDate).toUTC().toISO()}`; | |
} else { | |
esm241Output.textContent = "Invalid"; | |
esm241OutputUTC.textContent = ""; | |
} | |
// JS Date | |
const jsDate = new Date(text); | |
jsOutput.textContent = isNaN(jsDate.getTime()) ? "Invalid" : jsDate.toISOString(); | |
} | |
update(input.value); | |
input.addEventListener("keyup", () => { | |
update(input.value); | |
}); | |
// static tests | |
const testCases = [ | |
"5/1", | |
"5/1/2025", | |
"05/01/2025", | |
"5/31", | |
"6/1", | |
"12/31/2025", | |
"1/1/2026", | |
"1-1-2025", | |
"1-13-2025", | |
"1-13-25", | |
"Apr 01", | |
"Apr-01", | |
"tomorrow", | |
"next Friday", | |
"yesterday", | |
"last Monday", | |
"1 May 2025", | |
"May 1, 2025", | |
]; | |
const tbody = document.getElementById("testTable"); | |
for (const test of testCases) { | |
let chronoLocal, chronoUtc, js; | |
try { | |
const chronoDate = chrono241.parseDate(test); | |
chronoLocal = chronoDate ? chronoDate.toISOString() : "Invalid"; | |
chronoUtc = chronoDate | |
? luxon.DateTime.fromJSDate(chronoDate).toUTC().toISO() | |
: "Invalid"; | |
} catch (e) { | |
chronoLocal = chronoUtc = "Invalid"; | |
} | |
const jsDate = new Date(test); | |
js = isNaN(jsDate.getTime()) ? "Invalid" : jsDate.toISOString(); | |
const tr = document.createElement("tr"); | |
tr.innerHTML = ` | |
<td>${test}</td> | |
<td>${chronoLocal}</td> | |
<td>${chronoUtc}</td> | |
<td>${js}</td> | |
`; | |
tbody.appendChild(tr); | |
} | |
// luxon hardcoded | |
const luxonTests = [ | |
{ input: "5/1/25", format: "M/d/yy" }, | |
{ input: "5/1/2025", format: "M/d/yyyy" }, | |
{ input: "05/01/2025", format: "MM/dd/yyyy" }, | |
{ input: "1-13-25", format: "M-d-yy" }, | |
]; | |
const luxonTable = document.getElementById("luxonTable"); | |
luxonTests.forEach(({ input, format }) => { | |
const dt = luxon.DateTime.fromFormat(input, format); | |
const tr = document.createElement("tr"); | |
tr.innerHTML = ` | |
<td>${input}</td> | |
<td>${dt.isValid ? dt.toFormat("yyyy-MM-dd HH:mm") : "Invalid"}</td> | |
<td>${dt.isValid ? dt.toISO() : "Invalid"}</td> | |
`; | |
luxonTable.appendChild(tr); | |
}); | |
</script> | |
<script> | |
document.querySelector(".luxon-out").innerHTML = ` | |
Luxon now: ${luxon.DateTime.now().toISO()} | |
`; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment