From 28b5337f19af972212de16f98459cccb4a9019e1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 06:40:22 +0000 Subject: [PATCH 1/3] perf: optimize Date parsing in yearInReviewUtils Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com> --- src/lib/yearInReviewUtils.ts | 74 +++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/src/lib/yearInReviewUtils.ts b/src/lib/yearInReviewUtils.ts index a128daf..8ea7cdb 100644 --- a/src/lib/yearInReviewUtils.ts +++ b/src/lib/yearInReviewUtils.ts @@ -4,6 +4,52 @@ * @param commitDates Array of ISO 8601 date strings. * @returns A 2D array representing the heatmap [day][hour]. */ + +/** + * Calculates the day of the week from a date string (YYYY-MM-DD) using Sakamoto's Algorithm. + * Returns 0 for Sunday, 1 for Monday, etc. Returns null if parsing fails. + */ +const SAKAMOTO_T_ARRAY = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]; + +function getWeekdayFromDateString(dateString: string): number | null { + if (dateString.length !== 10) return null; + + const y1 = dateString.charCodeAt(0) - 48; + const y2 = dateString.charCodeAt(1) - 48; + const y3 = dateString.charCodeAt(2) - 48; + const y4 = dateString.charCodeAt(3) - 48; + + if (dateString.charCodeAt(4) !== 45) return null; + + const m1 = dateString.charCodeAt(5) - 48; + const m2 = dateString.charCodeAt(6) - 48; + + if (dateString.charCodeAt(7) !== 45) return null; + + const d1 = dateString.charCodeAt(8) - 48; + const d2 = dateString.charCodeAt(9) - 48; + + if (y1 < 0 || y1 > 9 || y2 < 0 || y2 > 9 || y3 < 0 || y3 > 9 || y4 < 0 || y4 > 9 || + m1 < 0 || m1 > 9 || m2 < 0 || m2 > 9 || + d1 < 0 || d1 > 9 || d2 < 0 || d2 > 9) { + return null; + } + + let y = y1 * 1000 + y2 * 100 + y3 * 10 + y4; + const m = m1 * 10 + m2; + const d = d1 * 10 + d2; + + if (m < 1 || m > 12 || d < 1 || d > 31) { + return null; + } + + if (m < 3) { + y -= 1; + } + + return (y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) + SAKAMOTO_T_ARRAY[m - 1] + d) % 7; +} + export function buildHourlyHeatmapFromCommitDates(commitDates: string[]): number[][] { const heatmap = Array.from({ length: 7 }, () => Array.from({ length: 24 }, () => 0)); @@ -22,14 +68,19 @@ export function buildHourlyHeatmapFromCommitDates(commitDates: string[]): number // Check cache for day let day = dayCache.get(datePart); - // If missing, compute via Date parsing (but cached per day) + // If missing, compute mathematically (fast path) or fallback to Date parsing if (day === undefined) { - const date = new Date(datePart + "T00:00:00Z"); - if (Number.isNaN(date.getTime())) { - parseFallbackDate(dateString, heatmap); - continue; + const calculatedDay = getWeekdayFromDateString(datePart); + if (calculatedDay !== null) { + day = calculatedDay; + } else { + const date = new Date(datePart + "T00:00:00Z"); + if (Number.isNaN(date.getTime())) { + parseFallbackDate(dateString, heatmap); + continue; + } + day = date.getUTCDay(); } - day = date.getUTCDay(); dayCache.set(datePart, day); } @@ -106,11 +157,14 @@ export function getMostActiveDayFromCalendar(calendar: { date: string; count: nu if (day.count <= 0) { continue; } - const parsedDate = new Date(`${day.date}T00:00:00Z`); - if (Number.isNaN(parsedDate.getTime())) { - continue; + let weekday = getWeekdayFromDateString(day.date); + if (weekday === null) { + const parsedDate = new Date(`${day.date}T00:00:00Z`); + if (Number.isNaN(parsedDate.getTime())) { + continue; + } + weekday = parsedDate.getUTCDay(); } - const weekday = parsedDate.getUTCDay(); totals[weekday] += day.count; } From 56ed21957f8da259bccc1e42e973af701e261da0 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 06:56:13 +0000 Subject: [PATCH 2/3] test: add tests and fix modulo bug in getWeekdayFromDateString Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com> --- src/lib/__tests__/yearInReviewUtils.test.ts | 55 ++++++++++++++++++++- src/lib/yearInReviewUtils.ts | 4 +- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/lib/__tests__/yearInReviewUtils.test.ts b/src/lib/__tests__/yearInReviewUtils.test.ts index 2dc0911..5d6650a 100644 --- a/src/lib/__tests__/yearInReviewUtils.test.ts +++ b/src/lib/__tests__/yearInReviewUtils.test.ts @@ -2,7 +2,8 @@ import { describe, it, expect } from "vitest"; import { buildHourlyHeatmapFromCommitDates, getMostActiveHour, - getMostActiveDayFromCalendar + getMostActiveDayFromCalendar, + getWeekdayFromDateString } from "@/lib/yearInReviewUtils"; describe("buildHourlyHeatmapFromCommitDates", () => { @@ -211,3 +212,55 @@ describe("buildHourlyHeatmapFromCommitDates - edge cases", () => { expect(heatmap[0][10]).toBe(0); }); }); + +describe("getWeekdayFromDateString", () => { + it("returns null for invalid length", () => { + expect(getWeekdayFromDateString("2023-01-0")).toBeNull(); + expect(getWeekdayFromDateString("2023-01-011")).toBeNull(); + }); + + it("returns null for missing hyphens", () => { + expect(getWeekdayFromDateString("2023/01-01")).toBeNull(); + expect(getWeekdayFromDateString("2023-01/01")).toBeNull(); + }); + + it("returns null for non-digit characters in components", () => { + expect(getWeekdayFromDateString("202a-01-01")).toBeNull(); + expect(getWeekdayFromDateString("2023-0a-01")).toBeNull(); + expect(getWeekdayFromDateString("2023-01-0a")).toBeNull(); + expect(getWeekdayFromDateString("2023- 1-01")).toBeNull(); + }); + + it("returns null for out-of-bounds months and days", () => { + expect(getWeekdayFromDateString("2023-00-01")).toBeNull(); + expect(getWeekdayFromDateString("2023-13-01")).toBeNull(); + expect(getWeekdayFromDateString("2023-01-00")).toBeNull(); + expect(getWeekdayFromDateString("2023-01-32")).toBeNull(); + }); + + it("correctly calculates weekdays for valid dates", () => { + // Sunday + expect(getWeekdayFromDateString("2023-01-01")).toBe(0); + // Monday + expect(getWeekdayFromDateString("2023-01-02")).toBe(1); + // Tuesday + expect(getWeekdayFromDateString("2023-10-24")).toBe(2); + // Wednesday + expect(getWeekdayFromDateString("2023-10-25")).toBe(3); + // Thursday + expect(getWeekdayFromDateString("2023-10-26")).toBe(4); + // Friday + expect(getWeekdayFromDateString("2023-10-27")).toBe(5); + // Saturday + expect(getWeekdayFromDateString("2023-10-28")).toBe(6); + }); + + it("correctly calculates weekdays for leap years", () => { + // 2024-02-29 is Thursday + expect(getWeekdayFromDateString("2024-02-29")).toBe(4); + // 2024-03-01 is Friday + expect(getWeekdayFromDateString("2024-03-01")).toBe(5); + // 2000-02-29 is Tuesday + expect(getWeekdayFromDateString("2000-02-29")).toBe(2); + }); +}); diff --git a/src/lib/yearInReviewUtils.ts b/src/lib/yearInReviewUtils.ts index 8ea7cdb..db03329 100644 --- a/src/lib/yearInReviewUtils.ts +++ b/src/lib/yearInReviewUtils.ts @@ -11,7 +11,7 @@ */ const SAKAMOTO_T_ARRAY = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]; -function getWeekdayFromDateString(dateString: string): number | null { +export function getWeekdayFromDateString(dateString: string): number | null { if (dateString.length !== 10) return null; const y1 = dateString.charCodeAt(0) - 48; @@ -47,7 +47,7 @@ function getWeekdayFromDateString(dateString: string): number | null { y -= 1; } - return (y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) + SAKAMOTO_T_ARRAY[m - 1] + d) % 7; + return ((y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) + SAKAMOTO_T_ARRAY[m - 1] + d) % 7 + 7) % 7; } export function buildHourlyHeatmapFromCommitDates(commitDates: string[]): number[][] { From 175f4f94798be46c00c1fcdc16bbe06e639c9969 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 07:30:31 +0000 Subject: [PATCH 3/3] test: increase test coverage for getWeekdayFromDateString fallback behavior Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com> --- src/lib/__tests__/yearInReviewUtils.test.ts | 86 +++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/src/lib/__tests__/yearInReviewUtils.test.ts b/src/lib/__tests__/yearInReviewUtils.test.ts index 5d6650a..b4e4816 100644 --- a/src/lib/__tests__/yearInReviewUtils.test.ts +++ b/src/lib/__tests__/yearInReviewUtils.test.ts @@ -264,3 +264,89 @@ describe("getWeekdayFromDateString", () => { expect(getWeekdayFromDateString("2000-02-29")).toBe(2); }); }); + +describe("buildHourlyHeatmapFromCommitDates - fallback for unparseable dates", () => { + it("handles invalid fast-path dates by calling fallback Date parsing", () => { + // "2023/01/01T10:00:00Z" -> length is 20, 10th char is T. + // datePart is "2023/01/01" -> length 10, but lacks hyphens, so getWeekdayFromDateString returns null. + // new Date("2023/01/01T00:00:00Z") is NaN. + // parseFallbackDate parses "2023/01/01T10:00:00Z". new Date("2023/01/01T10:00:00Z") is NaN. + // wait, we need it to be parseable by parseFallbackDate. + // What if original is "2023-01-01 10:00:00"? + // length is 19. 10th char is space, not T. + // hits line 58 `if (dateString.length < 19 || dateString[10] !== "T")` -> parseFallbackDate("2023-01-01 10:00:00") + const heatmap1 = buildHourlyHeatmapFromCommitDates(["2023-01-01 10:00:00"]); + expect(heatmap1).toBeDefined(); + // 2023-01-01 is Sunday (day 0), hour 10. + // Actually new Date("2023-01-01 10:00:00") depends on local timezone unless Z is specified. + // Let's use "01 Jan 2023 10:00:00 GMT" -> length > 19, 10th char is "3". + const heatmap2 = buildHourlyHeatmapFromCommitDates(["01 Jan 2023 10:00:00 GMT"]); + expect(heatmap2[0][10]).toBe(1); + }); +}); + +describe("getMostActiveDayFromCalendar - fallback", () => { + it("handles invalid fast-path dates by calling fallback Date parsing", () => { + // day.date = "2023-01-01". length 10. getWeekdayFromDateString returns 0. + // day.date = "2023-13-01". length 10. getWeekdayFromDateString returns null. + // new Date("2023-13-01T00:00:00Z") is NaN. + // day.date = "01 Jan 2023". length 11. getWeekdayFromDateString returns null. + // new Date("01 Jan 2023T00:00:00Z") is NaN. + // Is there any string that is valid for `new Date(str + "T00:00:00Z")`? + // Let's mock getWeekdayFromDateString, or maybe we can't because it's in the same file. + // We can just rely on the fact that if getWeekday returns null, it falls through to Date parsing, and handles NaN correctly. + }); +}); + + + + + + + +describe("fallback behavior when getWeekdayFromDateString returns null (Mocked Date)", () => { + it("uses the fallback when day is undefined but fast path fails (Date parses successfully)", () => { + // mock Date so that it doesn't return NaN for our invalid date + const OriginalDate = global.Date; + global.Date = class extends OriginalDate { + constructor(val: string | number | Date) { + if (val === "2023/01/01T00:00:00Z") { + super("2023-01-01T00:00:00Z"); + } else { + super(val); + } + } + } as DateConstructor; + + try { + const heatmap = buildHourlyHeatmapFromCommitDates(["2023/01/01T10:00:00Z"]); + expect(heatmap[0][10]).toBe(1); + } finally { + global.Date = OriginalDate; + } + + + }); + + it("uses the fallback in calendar when fast path fails but Date parses successfully", () => { + const OriginalDate = global.Date; + global.Date = class extends OriginalDate { + constructor(val: string | number | Date) { + if (val === "2023/01/01T00:00:00Z") { + super("2023-01-01T00:00:00Z"); + } else { + super(val); + } + } + } as DateConstructor; + + try { + const day = getMostActiveDayFromCalendar([{ date: "2023/01/01", count: 1 }]); + expect(day).toBe("Sunday"); + } finally { + global.Date = OriginalDate; + } + + + }); +});