Add date range helpers for day tabs

This commit is contained in:
2026-04-17 00:15:20 +03:00
parent 1232587774
commit 9522f235cf
2 changed files with 101 additions and 0 deletions
@@ -0,0 +1,58 @@
import { describe, it, expect } from "vitest";
import { formatYyyymmdd, parseYyyymmdd, generateDateRange, findPageIndex } from "./dateRange.js";
describe("formatYyyymmdd", () => {
it("formats a Date to yyyymmdd", () => {
expect(formatYyyymmdd(new Date(2026, 3, 16))).toBe("20260416");
});
it("pads single-digit month and day", () => {
expect(formatYyyymmdd(new Date(2026, 0, 5))).toBe("20260105");
});
});
describe("parseYyyymmdd", () => {
it("parses yyyymmdd into Date", () => {
const d = parseYyyymmdd("20260416");
expect(d.getFullYear()).toBe(2026);
expect(d.getMonth()).toBe(3);
expect(d.getDate()).toBe(16);
});
});
describe("generateDateRange", () => {
it("generates dates from today-daysBefore to today+daysAfter inclusive", () => {
const today = new Date(2026, 3, 16);
const range = generateDateRange(today, 2, 3);
expect(range).toHaveLength(6);
expect(range[0]).toBe("20260414");
expect(range[2]).toBe("20260416");
expect(range[5]).toBe("20260419");
});
it("handles zero-range", () => {
const today = new Date(2026, 3, 16);
expect(generateDateRange(today, 0, 0)).toEqual(["20260416"]);
});
it("handles month boundaries", () => {
const today = new Date(2026, 3, 1);
const range = generateDateRange(today, 2, 0);
expect(range).toEqual(["20260330", "20260331", "20260401"]);
});
});
describe("findPageIndex", () => {
it("finds page index for the given date at pageSize=7", () => {
const dates = ["20260414", "20260415", "20260416", "20260417", "20260418", "20260419", "20260420", "20260421", "20260422"];
expect(findPageIndex(dates, "20260414", 7)).toBe(0);
expect(findPageIndex(dates, "20260420", 7)).toBe(0);
expect(findPageIndex(dates, "20260421", 7)).toBe(1);
expect(findPageIndex(dates, "20260422", 7)).toBe(1);
});
it("returns 0 when date not found", () => {
const dates = ["20260414", "20260415"];
expect(findPageIndex(dates, "20260999", 7)).toBe(0);
});
});
@@ -0,0 +1,43 @@
/**
* Pure helper functions for generating and navigating date ranges
* in the DayTabs component. No React, no side effects.
*/
/** Format a Date as yyyymmdd (zero-padded). */
export function formatYyyymmdd(d: Date): string {
const y = d.getFullYear().toString();
const m = (d.getMonth() + 1).toString().padStart(2, "0");
const day = d.getDate().toString().padStart(2, "0");
return `${y}${m}${day}`;
}
/** Parse a yyyymmdd string into a local Date. */
export function parseYyyymmdd(s: string): Date {
const y = parseInt(s.slice(0, 4), 10);
const m = parseInt(s.slice(4, 6), 10) - 1;
const day = parseInt(s.slice(6, 8), 10);
return new Date(y, m, day);
}
/**
* Generate an inclusive list of yyyymmdd strings spanning
* [base - daysBefore, base + daysAfter].
*/
export function generateDateRange(base: Date, daysBefore: number, daysAfter: number): string[] {
const result: string[] = [];
for (let offset = -daysBefore; offset <= daysAfter; offset++) {
const d = new Date(base.getFullYear(), base.getMonth(), base.getDate() + offset);
result.push(formatYyyymmdd(d));
}
return result;
}
/**
* Find the page index (0-based) containing the given date, paginated by pageSize.
* Returns 0 if the date is not in the list.
*/
export function findPageIndex(dates: string[], target: string, pageSize: number): number {
const idx = dates.indexOf(target);
if (idx < 0) return 0;
return Math.floor(idx / pageSize);
}