Skip to content

Commit 7fe9152

Browse files
authored
feat: add StringDateAdapter (#21174)
closes #20967
1 parent 35b3304 commit 7fe9152

File tree

5 files changed

+386
-7
lines changed

5 files changed

+386
-7
lines changed

packages/docs/src/pages/en/features/dates.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,3 +370,19 @@ declare module 'vuetify' {
370370
}
371371
}
372372
```
373+
374+
## String adapter
375+
376+
<DocIntroduced version="3.9.0" />
377+
378+
Date objects can be inconvenient to work with, especially if you're just passing the value straight to a fetch request. Vuetify also exports a StringDateAdapter that will cause date components to emit strings instead.
379+
380+
```ts { resource="src/plugins/vuetify.js" }
381+
import { StringDateAdapter } from 'vuetify/date/adapters/string'
382+
383+
export default createVuetify({
384+
date: {
385+
adapter: StringDateAdapter,
386+
},
387+
})
388+
```

packages/vuetify/dev/vuetify/date.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { StringDateAdapter } from '@/composables/date/adapters/string'
12
// import DateFnsAdapter from '@date-io/date-fns'
23
// import { enAU, enUS, ja, sv } from 'date-fns/locale'
34

@@ -9,6 +10,7 @@
910

1011
export default {
1112
// adapter: DateFnsAdapter,
13+
adapter: StringDateAdapter,
1214
formats: {
1315
// dayOfMonth: date => date.getDate(),
1416
},

packages/vuetify/src/composables/date/DateAdapter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ export interface DateAdapter<T = unknown> {
1515
endOfYear (date: T): T
1616

1717
isAfter (date: T, comparing: T): boolean
18-
isAfterDay(value: T, comparing: T): boolean
18+
isAfterDay(date: T, comparing: T): boolean
1919

2020
isSameDay (date: T, comparing: T): boolean
2121
isSameMonth (date: T, comparing: T): boolean
22-
isSameYear(value: T, comparing: T): boolean
22+
isSameYear(date: T, comparing: T): boolean
2323

2424
isBefore (date: T, comparing: T): boolean
2525
isEqual (date: T, comparing: T): boolean

packages/vuetify/src/composables/date/__tests__/date.spec.ts

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Utilities
2+
import { StringDateAdapter } from '../adapters/string'
23
import { VuetifyDateAdapter } from '../adapters/vuetify'
34

45
// Types
@@ -7,12 +8,16 @@ import type { DateAdapter } from '../DateAdapter'
78

89
function expectAssignable<T, T2 extends T = T> (value: T2): void {}
910

10-
describe('date.ts', () => {
11-
// Cannot define properties that don't exist in date-io
12-
expectAssignable<DateAdapter>({} as IUtils<Date, string>)
13-
// @ts-expect-error Can implement a subset of date-io
14-
expectAssignable<IUtils<Date>>({} as DateAdapter)
11+
describe('date', () => {
12+
it('types', () => {
13+
// Cannot define properties that don't exist in date-io
14+
expectAssignable<DateAdapter>({} as IUtils<Date, string>)
15+
// @ts-expect-error Can implement a subset of date-io
16+
expectAssignable<IUtils<Date>>({} as DateAdapter)
17+
})
18+
})
1519

20+
describe('VuetifyDateAdapter', () => {
1621
it('should have the correct days in a month', () => {
1722
const adapter = new VuetifyDateAdapter({ locale: 'en-US' })
1823

@@ -90,3 +95,82 @@ describe('date.ts', () => {
9095
expect(adapter2.getWeek(new Date('2025-01-06'))).toBe(2) // monday
9196
})
9297
})
98+
99+
describe('StringDateAdapter', () => {
100+
it('should have the correct days in a month', () => {
101+
const adapter = new StringDateAdapter({ locale: 'en-US' })
102+
103+
expect(adapter.getWeek('2023-10-10')).toBe(41)
104+
})
105+
106+
it('should correctly calculate weeks between years', () => {
107+
const adapter = new StringDateAdapter({ locale: 'en-US' })
108+
109+
expect(adapter.getWeek('2024-12-28')).toBe(52)
110+
expect(adapter.getWeek('2024-12-29')).toBe(1)
111+
expect(adapter.getWeek('2024-12-30')).toBe(1)
112+
expect(adapter.getWeek('2024-12-31')).toBe(1)
113+
expect(adapter.getWeek('2025-01-01')).toBe(1)
114+
expect(adapter.getWeek('2025-01-02')).toBe(1)
115+
expect(adapter.getWeek('2025-01-03')).toBe(1)
116+
expect(adapter.getWeek('2025-01-04')).toBe(1)
117+
expect(adapter.getWeek('2025-01-05')).toBe(2)
118+
})
119+
120+
it('should correctly calculate when year starts with a full week', () => {
121+
const adapter1 = new StringDateAdapter({ locale: 'en-US' }) // first day = 7 | minimal days = 1
122+
123+
expect(adapter1.getWeek('2022-12-25')).toBe(53)
124+
expect(adapter1.getWeek('2022-12-31')).toBe(53)
125+
expect(adapter1.getWeek('2023-01-01')).toBe(1)
126+
expect(adapter1.getWeek('2023-01-07')).toBe(1)
127+
128+
const adapter2 = new StringDateAdapter({ locale: 'pt' }) // first day = 7 | minimal days = 4
129+
130+
expect(adapter2.getWeek('2022-12-25')).toBe(52)
131+
expect(adapter2.getWeek('2022-12-31')).toBe(52)
132+
expect(adapter2.getWeek('2023-01-01')).toBe(1)
133+
expect(adapter2.getWeek('2023-01-07')).toBe(1)
134+
})
135+
136+
it('should adjust for start of a week', () => {
137+
const adapter = new StringDateAdapter({ locale: 'en-US' }) // first day = 7 | minimal days = 1
138+
139+
expect(adapter.getWeek('2028-12-25', 1)).toBe(53)
140+
expect(adapter.getWeek('2028-12-31', 1)).toBe(53)
141+
expect(adapter.getWeek('2029-01-01', 1)).toBe(1)
142+
expect(adapter.getWeek('2029-01-07', 1)).toBe(1)
143+
144+
const adapter2 = new StringDateAdapter({ locale: 'pt-PT' }) // first day = 7 | minimal days = 4
145+
146+
expect(adapter2.getWeek('2024-12-28', 1)).toBe(52)
147+
expect(adapter2.getWeek('2024-12-29', 1)).toBe(52)
148+
expect(adapter2.getWeek('2024-12-30', 1)).toBe(1)
149+
expect(adapter2.getWeek('2024-12-31', 1)).toBe(1)
150+
expect(adapter2.getWeek('2025-01-01', 1)).toBe(1)
151+
expect(adapter2.getWeek('2025-01-02', 1)).toBe(1)
152+
expect(adapter2.getWeek('2025-01-03', 1)).toBe(1)
153+
expect(adapter2.getWeek('2025-01-04', 1)).toBe(1)
154+
expect(adapter2.getWeek('2025-01-05', 1)).toBe(1)
155+
expect(adapter2.getWeek('2025-01-06', 1)).toBe(2)
156+
expect(adapter2.getWeek('2025-01-07', 1)).toBe(2)
157+
158+
expect(adapter2.getWeek('2028-12-25', 1)).toBe(52)
159+
expect(adapter2.getWeek('2028-12-31', 1)).toBe(52)
160+
expect(adapter2.getWeek('2029-01-01', 1)).toBe(1)
161+
expect(adapter2.getWeek('2029-01-07', 1)).toBe(1)
162+
163+
const adapter3 = new StringDateAdapter({ locale: 'pl-PL' })
164+
expect(adapter3.getWeek('2024-12-29', 1)).toBe(52)
165+
})
166+
167+
it('should adjust fallback to week start from locale', () => {
168+
const adapter1 = new StringDateAdapter({ locale: 'en-US' })
169+
expect(adapter1.getWeek('2025-01-04')).toBe(1) // saturday
170+
expect(adapter1.getWeek('2025-01-05')).toBe(2) // sunday
171+
172+
const adapter2 = new StringDateAdapter({ locale: 'fr' })
173+
expect(adapter2.getWeek('2025-01-05')).toBe(1) // sunday
174+
expect(adapter2.getWeek('2025-01-06')).toBe(2) // monday
175+
})
176+
})

0 commit comments

Comments
 (0)