Skip to content

Commit

Permalink
fix: update useIsLive hook to account for timezone/DST
Browse files Browse the repository at this point in the history
  • Loading branch information
lachieh committed Nov 27, 2024
1 parent 5e71654 commit e2f55de
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 45 deletions.
100 changes: 56 additions & 44 deletions src/pages/_hooks/use-is-live.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import * as React from 'react';

const LIVE_NOW = 'Live now!';

/** This one is specifically used to set the time using Date.setUTCHours()
*/
type TimeHourMinuteSecondMilli = [number, number, number, number];
const START: TimeHourMinuteSecondMilli = [17, 0, 0, 0];
const END: TimeHourMinuteSecondMilli = [18, 0, 0, 0];
const DAYS_MS = 24 * 60 * 60 * 1000;
const HOURS_MS = 60 * 60 * 1000;
const MINUTES_MS = 60 * 1000;
const TEN_MINUTES_MS = 10 * MINUTES_MS;

function useIsLive() {
const [countdown, setCountdown] = React.useState('Join us!');
Expand All @@ -16,23 +15,27 @@ function useIsLive() {

function updateCountdown() {
const now = new Date();
const wednesday = getWednesday();
const [start, end] = getStartEnd(wednesday);

if (now >= start && now <= end) {
setCountdown(LIVE_NOW);
} else {
// calculate the time until the next wasmCloud Wednesday
const diff = wednesday.getTime() - now.getTime();
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));

// update the countdown
setCountdown(`${days ? `${days}d ` : ''}${hours ? `${hours}h ` : ''}${minutes}m`);
}
try {
const [start, end] = getStartEnd();

if (now >= start && now <= end) {
setCountdown(LIVE_NOW);
} else {
// calculate the time until the next wasmCloud Wednesday
const diff = start.getTime() - now.getTime();
const days = Math.floor(diff / DAYS_MS);
const hours = Math.floor((diff % DAYS_MS) / HOURS_MS);
const minutes = Math.floor((diff % HOURS_MS) / MINUTES_MS);

// update the countdown
setCountdown(`${days ? `${days}d ` : ''}${hours ? `${hours}h ` : ''}${minutes}m`);
}

timeout = setTimeout(updateCountdown, 60 * 1000); // 60 seconds
timeout = setTimeout(updateCountdown, 60 * 1000); // 60 seconds
} catch {
// unable to determine dates, just show the default message
setCountdown('Join us!');
}
}

updateCountdown();
Expand All @@ -43,37 +46,46 @@ function useIsLive() {
}, []);

const isLive = countdown === LIVE_NOW;
const wednesday = getWednesday();
const [start, end] = getStartEnd(wednesday);
const tenMinutesBefore = new Date(start.getTime() - 10 * 60 * 1000);
const [start] = getStartEnd();
const tenMinutesBeforeStart = new Date(start.getTime() - TEN_MINUTES_MS);
const now = new Date();
const showLinks = isLive || now >= tenMinutesBefore;
const showLinks = isLive || now >= tenMinutesBeforeStart;

return { countdown, isLive, showLinks };
}

return { countdown, isLive, showLinks, wednesday, start, end };
function getStartEnd() {
const start = new Date(nextWednesdayInNewYork());
const end = new Date(start);
end.setHours(start.getHours() + 1);
return [start, end];
}

function getWednesday() {
function nextWednesdayInNewYork() {
const now = new Date();
const wednesday = new Date();
wednesday.setUTCHours(...START);
if (now.getUTCDay() <= 3) {
wednesday.setDate(wednesday.getDate() + (3 - now.getUTCDay()));
const wednesday = new Date(now);

// We are using UTC time here, since we're going to append the NY offset
if (now.getUTCDay() < 3) {
wednesday.setUTCDate(wednesday.getUTCDate() + (3 - now.getUTCDay()));
} else {
wednesday.setDate(wednesday.getDate() + (10 - now.getUTCDay()));
}
const [, end] = getStartEnd(wednesday);
if (now >= end) {
wednesday.setDate(wednesday.getDate() + 7);
wednesday.setUTCDate(wednesday.getUTCDate() + (10 - now.getUTCDay()));
}
return wednesday;
}
wednesday.setUTCHours(12, 0, 0, 0);

function getStartEnd(time) {
const start = new Date(time.getTime());
start.setUTCHours(...START);
const end = new Date(time.getTime());
end.setUTCHours(...END);
return [start, end];
// Using Intl.DateTimeFormat to get the offset in the format we need. This
// accounts for Wednesdays that are in daylight saving time.
const offsetToNy = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/New_York',
timeZoneName: 'shortOffset',
hour: 'numeric',
})
.formatToParts()
.find(({ type }) => type === 'timeZoneName')
.value.replace(/GMT([+-]\d+)/, '$1:00')
.replace(/([+-])(\d:00)/, '$10$2');

return wednesday.toISOString().replace(/Z$/, offsetToNy);
}

export default useIsLive;
1 change: 0 additions & 1 deletion src/pages/_index/_components/get-involved/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import { Section, SectionColor } from '@site/src/pages/_components/section';
import { SectionHeading } from '@site/src/pages/_components/section-heading';
import { SectionTag } from '@site/src/pages/_components/section-tag';
import useIsLive from '@site/src/pages/_hooks/use-is-live';
import styles from './get-involved.module.css';
import { Links } from '@site/src/constants';
import { SectionContent } from '@site/src/pages/_components/section-content';
Expand Down

0 comments on commit e2f55de

Please sign in to comment.