fix(gsc): clamp month-based date ranges instead of overflowing short months (#133)
This commit is contained in:
parent
d7cfbec796
commit
3edbd0c11e
@ -46,6 +46,23 @@ describe("resolveDateRange", () => {
|
|||||||
);
|
);
|
||||||
expect(startDate).toBe("2026-01-01");
|
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", () => {
|
describe("buildSearchAnalyticsRequest", () => {
|
||||||
|
|||||||
@ -72,6 +72,19 @@ function formatDate(date: Date): string {
|
|||||||
return date.toISOString().slice(0, 10);
|
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 {
|
function subtractRange(end: Date, range: GscDateRange): Date {
|
||||||
const d = new Date(end);
|
const d = new Date(end);
|
||||||
switch (range) {
|
switch (range) {
|
||||||
@ -82,25 +95,19 @@ function subtractRange(end: Date, range: GscDateRange): Date {
|
|||||||
d.setUTCDate(d.getUTCDate() - 28);
|
d.setUTCDate(d.getUTCDate() - 28);
|
||||||
break;
|
break;
|
||||||
case "last_3_months":
|
case "last_3_months":
|
||||||
d.setUTCMonth(d.getUTCMonth() - 3);
|
return subtractUtcMonths(d, 3);
|
||||||
break;
|
|
||||||
case "last_6_months":
|
case "last_6_months":
|
||||||
d.setUTCMonth(d.getUTCMonth() - 6);
|
return subtractUtcMonths(d, 6);
|
||||||
break;
|
|
||||||
case "last_12_months":
|
case "last_12_months":
|
||||||
d.setUTCMonth(d.getUTCMonth() - 12);
|
return subtractUtcMonths(d, 12);
|
||||||
break;
|
|
||||||
case "last_16_months":
|
case "last_16_months":
|
||||||
d.setUTCMonth(d.getUTCMonth() - 16);
|
return subtractUtcMonths(d, 16);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sixteenMonthFloor(today: Date): string {
|
function sixteenMonthFloor(today: Date): string {
|
||||||
const d = new Date(today);
|
return formatDate(subtractUtcMonths(today, 16));
|
||||||
d.setUTCMonth(d.getUTCMonth() - 16);
|
|
||||||
return formatDate(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resolve a convenience `dateRange` or explicit start/end into GSC dates.
|
/** Resolve a convenience `dateRange` or explicit start/end into GSC dates.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user