%
/* ---- Next occurrence -------------------------------------------------
All arithmetic happens on a UTC Date that carries the *Eastern calendar
date*, never a wall-clock instant. That keeps day-of-week and day-adding
correct across DST without needing a timezone library. */
const TZ = site.timezone || "America/New_York";
const now = new Date();
const todayISO = new Intl.DateTimeFormat("en-CA", {
timeZone: TZ, year: "numeric", month: "2-digit", day: "2-digit",
}).format(now);
const hourET = Number(
new Intl.DateTimeFormat("en-US", { timeZone: TZ, hour: "2-digit", hourCycle: "h23" }).format(now)
) % 24;
const toDate = (iso) => { const [y, m, d] = iso.split("-").map(Number); return new Date(Date.UTC(y, m - 1, d)); };
const isoOf = (dt) => dt.toISOString().slice(0, 10);
let next = toDate(todayISO);
const first = toDate(site.firstEvent);
if (next < first) next = first;
while (next.getUTCDay() !== site.weekday) next.setUTCDate(next.getUTCDate() + 1);
if (isoOf(next) === todayISO && hourET >= (site.endHour24 || 21)) next.setUTCDate(next.getUTCDate() + 7);
const cancelled = site.cancelled || [];
let skippedWeek = null;
// Keep the FIRST skipped date: with two cancellations in a row the notice
// should name the soonest one people were expecting, not the last one.
while (cancelled.includes(isoOf(next))) {
if (!skippedWeek) skippedWeek = isoOf(next);
next.setUTCDate(next.getUTCDate() + 7);
}
const nextISO = isoOf(next);
const isTonight = nextISO === todayISO;
const fmtDate = (opts) => new Intl.DateTimeFormat("en-US", Object.assign({ timeZone: "UTC" }, opts)).format(next);
const nextLong = fmtDate({ weekday: "long", month: "long", day: "numeric" });
const nextShort = fmtDate({ weekday: "short", month: "short", day: "numeric" });
const weekdayName = new Intl.DateTimeFormat("en-US", { timeZone: "UTC", weekday: "long" }).format(next);
const heroLine = isTonight
? `Tonight at ${site.venue}, ${site.startTime} to ${site.endTime}. Grab a cue and meet the people building things in ${site.city}.`
: `Every ${weekdayName} at ${site.venue}, ${site.startTime} to ${site.endTime}. The next one is ${nextLong}.`;
const details = [
{ label: "When", value: `Every ${weekdayName}` },
{ label: "Time", value: `${site.startTime} to ${site.endTime}` },
{ label: "Where", value: `${site.venue}, ${site.city}`, href: site.mapUrl },
{ label: "Entry", value: site.entry },
];
%>
No Break on <%= new Intl.DateTimeFormat("en-US", { timeZone: "UTC", month: "long", day: "numeric" }).format(toDate(skippedWeek)) %>. Back on <%= nextLong %>.
We are building Gainesville's startup culture, one terrible pool shot at a time.
Whether you are an engineer, a designer, a business strategist, or just an ambitious person driven to build things from the ground up, this is your crowd.
Zero pool skills required. Seriously. We are here to build startups, not run the table.
What to expect
<% site.expect.forEach(function (item, i) { %>
<%= i === 1 ? " cell-tint" : "" %> reveal">
<%= item.title %>
<%= item.body %>
<% }) %>
RSVP for <%= isTonight ? "tonight" : nextLong %>
Not required, but it helps us know how many tables to hold. We will email you a reminder the day before.
You are on the list.
See you <%= isTonight ? "tonight" : nextLong %> at <%= site.venue %>, <%= site.startTime %>. Bring your ideas and a valid ID.