fix(gsc): clamp month-based date ranges instead of overflowing short months (#133)

This commit is contained in:
Shuvam Kumar 2026-07-23 19:27:25 +05:30 committed by GitHub
parent d7cfbec796
commit 3edbd0c11e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 11 deletions

View File

@ -46,6 +46,23 @@ describe("resolveDateRange", () => {
);
expect(startDate).toBe("2026-01-01");
});
it("subtracts calendar months without overflowing short months", () => {
const { startDate, endDate } = resolveDateRange(
{ dateRange: "last_3_months" },
new Date("2026-06-03T00:00:00Z"),
);
expect(startDate).toBe("2026-02-28");
expect(endDate).toBe("2026-05-31");
});
it("clamps the 16-month floor to the last valid day of a short month", () => {
const { startDate } = resolveDateRange(
{ dateRange: "last_16_months" },
new Date("2026-06-30T00:00:00Z"),
);
expect(startDate).toBe("2025-02-28");
});
});
describe("buildSearchAnalyticsRequest", () => {

View File

@ -72,6 +72,19 @@ function formatDate(date: Date): string {
return date.toISOString().slice(0, 10);
}
// Subtract calendar months in UTC, clamping the day to the target month's length.
function subtractUtcMonths(date: Date, months: number): Date {
const day = date.getUTCDate();
const d = new Date(date);
d.setUTCDate(1);
d.setUTCMonth(d.getUTCMonth() - months);
const daysInTargetMonth = new Date(
Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 0),
).getUTCDate();
d.setUTCDate(Math.min(day, daysInTargetMonth));
return d;
}
function subtractRange(end: Date, range: GscDateRange): Date {
const d = new Date(end);
switch (range) {
@ -82,25 +95,19 @@ function subtractRange(end: Date, range: GscDateRange): Date {
d.setUTCDate(d.getUTCDate() - 28);
break;
case "last_3_months":
d.setUTCMonth(d.getUTCMonth() - 3);
break;
return subtractUtcMonths(d, 3);
case "last_6_months":
d.setUTCMonth(d.getUTCMonth() - 6);
break;
return subtractUtcMonths(d, 6);
case "last_12_months":
d.setUTCMonth(d.getUTCMonth() - 12);
break;
return subtractUtcMonths(d, 12);
case "last_16_months":
d.setUTCMonth(d.getUTCMonth() - 16);
break;
return subtractUtcMonths(d, 16);
}
return d;
}
function sixteenMonthFloor(today: Date): string {
const d = new Date(today);
d.setUTCMonth(d.getUTCMonth() - 16);
return formatDate(d);
return formatDate(subtractUtcMonths(today, 16));
}
/** Resolve a convenience `dateRange` or explicit start/end into GSC dates.