Skip to content

Commit b30b986

Browse files
committed
fix(date-picker): wrong quarter presets
1 parent 012540b commit b30b986

File tree

2 files changed

+181
-3
lines changed

2 files changed

+181
-3
lines changed

packages/utilities/date-utils/src/preset.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function getDateRangePreset(preset: DateRangePreset, locale: string, time
2222
case "thisMonth":
2323
return [startOfMonth(today), today]
2424
case "thisQuarter":
25-
return [startOfMonth(today).add({ months: -today.month % 3 }), today]
25+
return [startOfMonth(today).add({ months: -((today.month - 1) % 3) }), today]
2626
case "thisYear":
2727
return [startOfYear(today), today]
2828
case "last3Days":
@@ -39,8 +39,8 @@ export function getDateRangePreset(preset: DateRangePreset, locale: string, time
3939
return [startOfMonth(today.add({ months: -1 })), endOfMonth(today.add({ months: -1 }))]
4040
case "lastQuarter":
4141
return [
42-
startOfMonth(today.add({ months: (-today.month % 3) - 3 })),
43-
endOfMonth(today.add({ months: (-today.month % 3) - 1 })),
42+
startOfMonth(today.add({ months: -((today.month - 1) % 3) - 3 })),
43+
endOfMonth(today.add({ months: -((today.month - 1) % 3) - 1 })),
4444
]
4545
case "lastWeek":
4646
return [startOfWeek(today, locale).add({ weeks: -1 }), endOfWeek(today, locale).add({ weeks: -1 })]
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import { CalendarDate } from "@internationalized/date"
2+
import { describe, expect, test, vi } from "vitest"
3+
import { getDateRangePreset } from "../src"
4+
5+
describe("getDateRangePreset", () => {
6+
const locale = "en-US"
7+
const timeZone = "UTC"
8+
9+
const mockToday = (year: number, month: number, day: number) => {
10+
vi.useFakeTimers()
11+
vi.setSystemTime(Date.UTC(year, month - 1, day, 12, 0, 0))
12+
return new CalendarDate(year, month, day)
13+
}
14+
15+
afterEach(() => {
16+
vi.useRealTimers()
17+
})
18+
19+
describe("thisQuarter", () => {
20+
test("Q1 (January)", () => {
21+
mockToday(2024, 1, 15)
22+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
23+
expect(start.toString()).toBe("2024-01-01")
24+
expect(end.toString()).toBe("2024-01-15")
25+
})
26+
27+
test("Q1 (February)", () => {
28+
mockToday(2024, 2, 20)
29+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
30+
expect(start.toString()).toBe("2024-01-01")
31+
expect(end.toString()).toBe("2024-02-20")
32+
})
33+
34+
test("Q1 (March)", () => {
35+
mockToday(2024, 3, 31)
36+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
37+
expect(start.toString()).toBe("2024-01-01")
38+
expect(end.toString()).toBe("2024-03-31")
39+
})
40+
41+
test("Q2 (April)", () => {
42+
mockToday(2024, 4, 10)
43+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
44+
expect(start.toString()).toBe("2024-04-01")
45+
expect(end.toString()).toBe("2024-04-10")
46+
})
47+
48+
test("Q2 (June)", () => {
49+
mockToday(2024, 6, 30)
50+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
51+
expect(start.toString()).toBe("2024-04-01")
52+
expect(end.toString()).toBe("2024-06-30")
53+
})
54+
55+
test("Q3 (July)", () => {
56+
mockToday(2024, 7, 1)
57+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
58+
expect(start.toString()).toBe("2024-07-01")
59+
expect(end.toString()).toBe("2024-07-01")
60+
})
61+
62+
test("Q3 (September)", () => {
63+
mockToday(2024, 9, 15)
64+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
65+
expect(start.toString()).toBe("2024-07-01")
66+
expect(end.toString()).toBe("2024-09-15")
67+
})
68+
69+
test("Q4 (October)", () => {
70+
mockToday(2024, 10, 5)
71+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
72+
expect(start.toString()).toBe("2024-10-01")
73+
expect(end.toString()).toBe("2024-10-05")
74+
})
75+
76+
test("Q4 (December)", () => {
77+
mockToday(2024, 12, 31)
78+
const [start, end] = getDateRangePreset("thisQuarter", locale, timeZone)
79+
expect(start.toString()).toBe("2024-10-01")
80+
expect(end.toString()).toBe("2024-12-31")
81+
})
82+
})
83+
84+
describe("lastQuarter", () => {
85+
test("Q1 → Q4 previous year", () => {
86+
mockToday(2024, 2, 15)
87+
const [start, end] = getDateRangePreset("lastQuarter", locale, timeZone)
88+
expect(start.toString()).toBe("2023-10-01")
89+
expect(end.toString()).toBe("2023-12-31")
90+
})
91+
92+
test("Q2 → Q1", () => {
93+
mockToday(2024, 5, 20)
94+
const [start, end] = getDateRangePreset("lastQuarter", locale, timeZone)
95+
expect(start.toString()).toBe("2024-01-01")
96+
expect(end.toString()).toBe("2024-03-31")
97+
})
98+
99+
test("Q3 → Q2", () => {
100+
mockToday(2024, 8, 10)
101+
const [start, end] = getDateRangePreset("lastQuarter", locale, timeZone)
102+
expect(start.toString()).toBe("2024-04-01")
103+
expect(end.toString()).toBe("2024-06-30")
104+
})
105+
106+
test("Q4 → Q3", () => {
107+
mockToday(2024, 11, 25)
108+
const [start, end] = getDateRangePreset("lastQuarter", locale, timeZone)
109+
expect(start.toString()).toBe("2024-07-01")
110+
expect(end.toString()).toBe("2024-09-30")
111+
})
112+
})
113+
114+
describe("other presets", () => {
115+
test("thisWeek", () => {
116+
mockToday(2024, 3, 14)
117+
const [start, end] = getDateRangePreset("thisWeek", locale, timeZone)
118+
expect(start.toString()).toBe("2024-03-10")
119+
expect(end.toString()).toBe("2024-03-16")
120+
})
121+
122+
test("thisMonth", () => {
123+
mockToday(2024, 3, 15)
124+
const [start, end] = getDateRangePreset("thisMonth", locale, timeZone)
125+
expect(start.toString()).toBe("2024-03-01")
126+
expect(end.toString()).toBe("2024-03-15")
127+
})
128+
129+
test("thisYear", () => {
130+
mockToday(2024, 6, 15)
131+
const [start, end] = getDateRangePreset("thisYear", locale, timeZone)
132+
expect(start.toString()).toBe("2024-01-01")
133+
expect(end.toString()).toBe("2024-06-15")
134+
})
135+
136+
test("last7Days", () => {
137+
mockToday(2024, 3, 15)
138+
const [start, end] = getDateRangePreset("last7Days", locale, timeZone)
139+
expect(start.toString()).toBe("2024-03-09")
140+
expect(end.toString()).toBe("2024-03-15")
141+
})
142+
143+
test("last30Days", () => {
144+
mockToday(2024, 3, 15)
145+
const [start, end] = getDateRangePreset("last30Days", locale, timeZone)
146+
expect(start.toString()).toBe("2024-02-15")
147+
expect(end.toString()).toBe("2024-03-15")
148+
})
149+
150+
test("lastMonth", () => {
151+
mockToday(2024, 3, 15)
152+
const [start, end] = getDateRangePreset("lastMonth", locale, timeZone)
153+
expect(start.toString()).toBe("2024-02-01")
154+
expect(end.toString()).toBe("2024-02-29")
155+
})
156+
157+
test("lastWeek", () => {
158+
mockToday(2024, 3, 14)
159+
const [start, end] = getDateRangePreset("lastWeek", locale, timeZone)
160+
expect(start.toString()).toBe("2024-03-03")
161+
expect(end.toString()).toBe("2024-03-09")
162+
})
163+
164+
test("lastYear", () => {
165+
mockToday(2024, 3, 15)
166+
const [start, end] = getDateRangePreset("lastYear", locale, timeZone)
167+
expect(start.toString()).toBe("2023-01-01")
168+
expect(end.toString()).toBe("2023-12-31")
169+
})
170+
})
171+
172+
test("invalid preset throws error", () => {
173+
mockToday(2024, 3, 15)
174+
expect(() => getDateRangePreset("invalidPreset" as any, locale, timeZone)).toThrow(
175+
"Invalid date range preset: invalidPreset",
176+
)
177+
})
178+
})

0 commit comments

Comments
 (0)