Created
December 1, 2022 00:08
-
-
Save Xevion/651061307321201c0d8ea90e8f60f7ad to your computer and use it in GitHub Desktop.
This file contains 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
import { z } from "zod"; | |
import { getMonth } from "date-fns"; | |
export const SeasonEnum = z.enum(["FALL", "SPRING"]); | |
export type Season = z.TypeOf<typeof SeasonEnum>; | |
export const SemesterSchema = z.object({ | |
season: SeasonEnum, | |
year: z.number().min(2000).max(2050), | |
}); | |
export type Semester = z.infer<typeof SemesterSchema>; | |
const semesterRanges: Record<Season, [number, number]> = { | |
[SeasonEnum.enum.FALL]: [8, 12], | |
[SeasonEnum.enum.SPRING]: [0, 4], | |
}; | |
/** | |
* Given a date, retrieve the season it resides within. | |
* @param time The date to operate on. Assumed UTC. | |
* @return {Season|null} The season, if the date is in one. If no seasons match, null is returned. | |
*/ | |
export const getSeason = (time: Date): Season | null => { | |
const semesterEntry = Object.entries(semesterRanges).find(([, [startMonth, endMonth]]) => { | |
const month = getMonth(time); | |
console.log({ month, startMonth, endMonth }); | |
return month >= startMonth && month <= endMonth; | |
}); | |
return semesterEntry != null ? (semesterEntry[0] as Season) : null; | |
}; | |
/** | |
* Given the date of a specific event, identify the semester it occurs within. | |
* @param time {Date} The date to operate on. Assumed UTC. | |
* @return {Semester|null} The semester (season & year) the date occurs within. If no seasons match, null is returned. | |
*/ | |
export const getSemester = (time: Date): Semester | null => { | |
const season = getSeason(time); | |
return season != null ? SemesterSchema.parse({ season, year: time.getUTCFullYear() }) : null; | |
}; | |
/** | |
* Calculate the start and end dates for a given Semester. | |
* This is useful for generating min/max values while filtering events in the database. | |
* @param season {Season} The season to use the range of. Spring, for example, might be January to May. | |
* @param year {number|null} The year of the date range. If null, it will default to the current year (UTC). | |
*/ | |
export const getSemesterRange = ( | |
season: Season, | |
year: number | null = null | |
): { start: Date; end: Date } => { | |
if (year == null) year = new Date().getUTCFullYear(); | |
const [startMonth, endMonth] = semesterRanges[season]; | |
return { | |
start: new Date(year, startMonth), | |
end: new Date(year, endMonth), | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment