← back to build-pages
refactor: extract startOfDayInTz + todayInTz helpers — DRY the tz math across /api/fleet/today + home
b57cacdaf296321e440329af57f5b7df4a0bc261 · 2026-05-13 20:37:02 -0700 · SteveStudio2
Files touched
Diff
commit b57cacdaf296321e440329af57f5b7df4a0bc261
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 20:37:02 2026 -0700
refactor: extract startOfDayInTz + todayInTz helpers — DRY the tz math across /api/fleet/today + home
---
server.js | 42 +++++++++++++++++++-----------------------
1 file changed, 19 insertions(+), 23 deletions(-)
diff --git a/server.js b/server.js
index e5be0b0..861a39e 100644
--- a/server.js
+++ b/server.js
@@ -354,13 +354,10 @@ app.get('/', async (req, res, next) => {
// Velocity counters + 7-day sparkline across the whole fleet. Concats
// per-project commit lists so the helper sees every commit in one shot.
const fleetCommits = entries.flatMap(e => _projectCache.get(e.slug)?.commits || []);
- // Today-in-PT count — server.tz-aware calendar boundary (Steve's day).
+ // Today-in-PT count — Steve's calendar day, not rolling-24h.
const todayPT = (() => {
- const todayStr = new Date().toLocaleString('sv-SE', { timeZone: 'America/Los_Angeles' }).slice(0, 10);
- const probe = new Date(`${todayStr}T00:00:00Z`);
- const fmt = probe.toLocaleString('sv-SE', { timeZone: 'America/Los_Angeles', hour12: false }).slice(0, 19).replace(' ', 'T');
- const fromTz = new Date(fmt).getTime();
- const startMs = probe.getTime() + (probe.getTime() - fromTz);
+ const todayStr = todayInTz('America/Los_Angeles');
+ const startMs = startOfDayInTz(todayStr, 'America/Los_Angeles');
const endMs = startMs + 86400000;
let n = 0;
for (const c of fleetCommits) {
@@ -756,25 +753,10 @@ app.get('/p/:slug/c/:hash', async (req, res, next) => {
// not rolling. ?tz= can override (e.g. ?tz=UTC).
app.get('/api/fleet/today', async (req, res, next) => {
const tz = typeof req.query.tz === 'string' ? req.query.tz : 'America/Los_Angeles';
- // sv-SE locale gives YYYY-MM-DD HH:MM:SS — easy slice + reliable boundary.
- const todayLocal = new Date().toLocaleString('sv-SE', { timeZone: tz }).slice(0, 10);
const dateStr = (typeof req.query.date === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(req.query.date))
? req.query.date
- : todayLocal;
- // Build the start-of-day in the target timezone, in ms. The trick is to
- // ask the same Date what midnight in that tz translates to in epoch ms —
- // we form the local-midnight string and pass it through Date.parse with the
- // tz offset implicit. Simpler approach: parse 00:00 in tz via formatToParts.
- const startMs = (() => {
- // YYYY-MM-DDT00:00:00 plus the tz offset on that date, computed by
- // formatting the candidate midnight in target tz and seeing how far it
- // drifts from UTC. Off-by-DST safe within ±1h, fine for our use.
- const probe = new Date(`${dateStr}T00:00:00Z`);
- const fmt = probe.toLocaleString('sv-SE', { timeZone: tz, hour12: false }).slice(0, 19).replace(' ', 'T');
- const fromTz = new Date(fmt).getTime();
- const offset = probe.getTime() - fromTz;
- return new Date(`${dateStr}T00:00:00Z`).getTime() + offset;
- })();
+ : todayInTz(tz);
+ const startMs = startOfDayInTz(dateStr, tz);
const endMs = startMs + 86400000;
try {
const all = [];
@@ -1010,6 +992,20 @@ function canonAuthor(name) {
return AUTHOR_ALIASES[key] || name;
}
+// Resolve the start-of-day epoch-ms for a YYYY-MM-DD date in the given IANA
+// timezone. Steve's wall clock is PT; UTC midnight at PT-evening straddles
+// "today" weirdly. This computes the same boundary the user sees on their
+// clock, DST-aware via Intl.
+function startOfDayInTz(dateStr, tz) {
+ const probe = new Date(`${dateStr}T00:00:00Z`);
+ const fmt = probe.toLocaleString('sv-SE', { timeZone: tz, hour12: false }).slice(0, 19).replace(' ', 'T');
+ const fromTz = new Date(fmt).getTime();
+ return probe.getTime() + (probe.getTime() - fromTz);
+}
+function todayInTz(tz) {
+ return new Date().toLocaleString('sv-SE', { timeZone: tz }).slice(0, 10);
+}
+
// Parse a ?since= query value into a unix ms cutoff (or 0 = no filter).
// Accepts 24h, 7d, 30m, or an ISO date prefix (YYYY-MM-DD…). Returns 0 for
// missing/malformed input so callers can use the result as a min-Date filter
← b709184 home: today-PT counter (Steve's calendar day, not rolling-24
·
back to build-pages
·
home: today vs yesterday side-by-side counts (Steve's PT cal ca0922f →