www-new/utils.ts

89 lines
2.1 KiB
TypeScript

import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz";
export const TERMS = ["winter", "spring", "fall"] as const;
export type Term = typeof TERMS[number];
export const DATE_FORMAT = "MMMM dd yyyy HH:mm";
// https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
export function isTerm(x: string): x is Term {
return TERMS.some((term) => x === term);
}
export function capitalize(str: string) {
return str.slice(0, 1).toUpperCase() + str.slice(1);
}
// Converts a date to local time
export function getLocalDateFromEST(date: Date): Date {
return utcToZonedTime(
// The date parameter is in EST
zonedTimeToUtc(date, "America/Toronto"),
Intl.DateTimeFormat().resolvedOptions().timeZone
);
}
export interface TermYear {
term: Term;
year: number;
}
export interface GetTermYearOptions {
goBackwards?: boolean;
skipCurrent?: boolean;
}
export function* getTermYear(
start?: number | TermYear,
{ goBackwards = false, skipCurrent = false }: GetTermYearOptions = {}
) {
const allTerms = [...TERMS];
if (goBackwards) {
allTerms.reverse();
}
const today = new Date();
const todayYear = today.getFullYear();
const todayTerm = TERMS[Math.trunc(today.getMonth() / 4)];
start ??= { term: todayTerm, year: todayYear };
if (typeof start === "number") {
start = { term: allTerms[0], year: start };
}
let currentYear = start.year;
while (0 <= currentYear && currentYear <= Number.MAX_SAFE_INTEGER) {
for (const currentTerm of allTerms) {
if (
currentYear === start.year &&
allTerms.indexOf(currentTerm) < allTerms.indexOf(start.term)
) {
continue;
}
if (
skipCurrent &&
currentYear === start.year &&
currentTerm === start.term
) {
continue;
}
yield { term: currentTerm, year: currentYear };
}
currentYear = currentYear + (goBackwards ? -1 : 1);
}
}
export function getCurrentTermYear() {
const result = getTermYear().next();
if (result.done === true) {
throw new Error("Cannot get current term. Iterator is done.");
}
return result.value;
}