useDate
Date manipulation using the Temporal API with locale-aware formatting and adapter support.
Installation
The built-in V0DateAdapter uses the runtime’s native Temporal implementation when available. Runtimes without native Temporal need the @js-temporal/polyfill optional peer:
pnpm add @js-temporal/polyfillnpm install @js-temporal/polyfillyarn add @js-temporal/polyfillbun add @js-temporal/polyfillThe Temporal API reached Stage 4↗︎ (finished) at TC39 in January 2026 and is part of ECMAScript 2026. The adapter prefers native Temporal and only falls back to the polyfill — once every runtime you target ships native support, the polyfill is no longer required.
Then install the date plugin with an adapter:
import { V0DateAdapter } from '@vuetify/v0/date'
import { createDatePlugin } from '@vuetify/v0'
app.use(
createDatePlugin({
adapter: new V0DateAdapter(),
locale: 'en-US',
})
) The adapter option is required. The V0DateAdapter is exported from a separate subpath (@vuetify/v0/date) to avoid bundling the Temporal polyfill unless explicitly used. If you don’t need date functionality, simply don’t install the plugin—no polyfill will be loaded.
Usage
Once the plugin is installed, use the useDate composable in any component:
Adapters
Adapters let you swap the underlying date library without changing your application code.
| Adapter | Import | Description |
|---|---|---|
V0DateAdapter | @vuetify/v0/date | Temporal API↗︎ adapter[1] |
DateAdapter Interface
The adapter provides a comprehensive API compatible with date-io↗︎:
abstract class DateAdapter<T> {
/** Current locale for formatting */
abstract get locale (): string
abstract set locale (value: string)
/** First day of week. 0=Sunday, 1=Monday, ... 6=Saturday. Managed by the plugin. */
abstract get firstDayOfWeek (): number
abstract set firstDayOfWeek (value: number)
// Construction & Conversion
abstract date (value?: unknown): T | null
abstract toJsDate (value: T): Date
abstract parseISO (date: string): T
abstract toISO (date: T): string
abstract parse (value: string, format: string): T | null
abstract isValid (date: unknown): date is T // Type predicate
abstract isNullish (value: T | null): value is null // Type predicate
// Locale & Formatting
abstract getCurrentLocaleCode (): string
abstract is12HourCycleInCurrentLocale (): boolean
abstract format (date: T, formatString: string): string
abstract formatByString (date: T, formatString: string): string
abstract getFormatHelperText (format: string): string
abstract formatNumber (numberToFormat: string): string
abstract getMeridiemText (ampm: 'am' | 'pm'): string
// Navigation
abstract startOfDay (date: T): T
abstract endOfDay (date: T): T
abstract startOfWeek (date: T): T
abstract endOfWeek (date: T): T
abstract startOfMonth (date: T): T
abstract endOfMonth (date: T): T
abstract startOfYear (date: T): T
abstract endOfYear (date: T): T
// Arithmetic
abstract addSeconds (date: T, amount: number): T
abstract addMinutes (date: T, amount: number): T
abstract addHours (date: T, amount: number): T
abstract addDays (date: T, amount: number): T
abstract addWeeks (date: T, amount: number): T
abstract addMonths (date: T, amount: number): T
abstract addYears (date: T, amount: number): T
// Comparison
abstract isAfter (date: T, comparing: T): boolean
abstract isAfterDay (date: T, comparing: T): boolean
abstract isAfterMonth (date: T, comparing: T): boolean
abstract isAfterYear (date: T, comparing: T): boolean
abstract isBefore (date: T, comparing: T): boolean
abstract isBeforeDay (date: T, comparing: T): boolean
abstract isBeforeMonth (date: T, comparing: T): boolean
abstract isBeforeYear (date: T, comparing: T): boolean
abstract isEqual (date: T, comparing: T): boolean
abstract isSameDay (date: T, comparing: T): boolean
abstract isSameMonth (date: T, comparing: T): boolean
abstract isSameYear (date: T, comparing: T): boolean
abstract isSameHour (date: T, comparing: T): boolean
abstract isWithinRange (date: T, range: [T, T]): boolean
// Getters
abstract getYear (date: T): number
abstract getMonth (date: T): number
abstract getDate (date: T): number
abstract getHours (date: T): number
abstract getMinutes (date: T): number
abstract getSeconds (date: T): number
abstract getDiff (date: T, comparing: T | string, unit?: string): number
abstract getWeek (date: T, minimalDays?: number): number
abstract getDaysInMonth (date: T): number
// Setters (immutable - returns new instance)
abstract setYear (date: T, year: number): T
abstract setMonth (date: T, month: number): T
abstract setDate (date: T, day: number): T
abstract setHours (date: T, hours: number): T
abstract setMinutes (date: T, minutes: number): T
abstract setSeconds (date: T, seconds: number): T
// Calendar Utilities
abstract getWeekdays (weekdayFormat?: 'long' | 'short' | 'narrow'): string[]
abstract getWeekArray (date: T): T[][]
abstract getMonthArray (date: T): T[]
abstract getYearRange (start: T, end: T): T[]
abstract getNextMonth (date: T): T
abstract getPreviousMonth (date: T): T
// Utility
abstract mergeDateAndTime (date: T, time: T): T
}Format Presets
The format() method accepts these preset format strings:
| Preset | Example Output |
|---|---|
fullDate | Saturday, June 15, 2024 |
fullDateWithWeekday | Saturday, June 15, 2024 |
normalDate | Jun 15, 2024 |
shortDate | 6/15/24 |
year | 2024 |
month | June |
monthShort | Jun |
monthAndYear | June 2024 |
monthAndDate | June 15 |
weekday | Saturday |
weekdayShort | Sat |
dayOfMonth | 15 |
hours12h | 10 AM |
hours24h | 10 |
minutes | 30 |
seconds | 45 |
fullTime | 10:30:45 AM |
fullTime12h | 10:30:45 AM |
fullTime24h | 10:30:45 |
fullDateTime | Saturday, June 15, 2024 at 10:30 AM |
keyboardDate | 06/15/2024 |
keyboardDateTime | 06/15/2024 10:30 AM |
Format Tokens
The formatByString() method supports these tokens:
| Token | Output | Example |
|---|---|---|
YYYY | 4-digit year | 2024 |
YY | 2-digit year | 24 |
MMMM | Full month name | June |
MMM | Short month name | Jun |
MM | Month (zero-padded) | 06 |
M | Month | 6 |
dddd | Full weekday name | Saturday |
ddd | Short weekday name | Sat |
DD | Day (zero-padded) | 15 |
D | Day | 15 |
HH | 24-hour (zero-padded) | 10 |
H | 24-hour | 10 |
hh | 12-hour (zero-padded) | 10 |
h | 12-hour | 10 |
mm | Minutes (zero-padded) | 30 |
m | Minutes | 30 |
ss | Seconds (zero-padded) | 45 |
s | Seconds | 45 |
A | AM/PM | AM |
a | am/pm | am |
Custom Adapters
The adapter pattern decouples date operations from the underlying library. When you call adapter.format(), the request flows through the provided adapter to its underlying date library:
Create custom adapters for different date libraries (date-fns, luxon, dayjs):
import { DateAdapter } from '@vuetify/v0'
import { isValid as dateFnsIsValid, parseISO, format as dateFnsFormat } from 'date-fns'
class DateFnsAdapter extends DateAdapter<Date> {
locale = 'en-US'
date (value?: unknown): Date | null {
if (value == null) return new Date()
if (value instanceof Date) return value
if (typeof value === 'string') return parseISO(value)
if (typeof value === 'number') return new Date(value)
return null
}
// Type predicate - enables TypeScript narrowing
isValid (date: unknown): date is Date {
return date instanceof Date && dateFnsIsValid(date)
}
// Type predicate - enables TypeScript narrowing
isNull (value: Date | null): value is null {
return value === null
}
format (date: Date, formatString: string): string {
return dateFnsFormat(date, this.getDateFnsFormat(formatString))
}
// Implement remaining methods...
}
// Use with plugin
app.use(
createDatePlugin({
adapter: new DateFnsAdapter(),
})
) The isValid and isNullish methods are type predicates. This enables TypeScript to narrow types after validation:
const date = adapter.date(input)
if (!adapter.isNullish(date) && adapter.isValid(date)) {
// TypeScript knows `date` is Date here
adapter.format(date, 'fullDate')
}Reactivity
The date context provides minimal reactivity, with the adapter being a static instance.
| Property | Reactive | Notes |
|---|---|---|
locale | Computed from useLocale if available | |
adapter | Static adapter instance |
Examples
The following example builds a complete, interactive date surface from adapter calls alone — no DatePicker component required.
Recipes
Locale Integration
When useLocale is available, useDate automatically syncs with the selected locale:
import { createApp } from 'vue'
import { V0DateAdapter } from '@vuetify/v0/date'
import { createLocalePlugin, createDatePlugin } from '@vuetify/v0'
const app = createApp(App)
// Install locale plugin first
app.use(
createLocalePlugin({
default: 'en',
messages: {
en: { /* ... */ },
de: { /* ... */ },
}
})
)
// Date plugin will auto-sync with locale
app.use(
createDatePlugin({
adapter: new V0DateAdapter(),
locales: {
en: 'en-US', // Map short codes to Intl locales
de: 'de-DE',
}
})
)When switching locales via useLocale, the date adapter automatically updates its formatting locale.
FAQ
The parse() method’s format parameter is currently ignored — the Temporal API doesn’t provide built-in format parsing, so the method delegates to date(), which handles ISO 8601 strings. For custom format parsing, use a library like date-fns or luxon with a custom adapter.
Date formatting can cause hydration mismatches in SSR applications because the server and client environments may produce different formatted output. Two effects are at play:
adapter.date()is environment-dependent by design. In the browser it returns the current time viaTemporal.Now.plainDateTimeISO(); on the server it returns the epoch (1970-01-01T00:00:00) for deterministic rendering. This is intentional, to prevent hydration mismatches — if an SSR app needs the current time, passDate.now()explicitly.Intl.DateTimeFormatuses the system timezone. Server environments (often UTC) and client browsers (the user’s local timezone) produce different formatted strings.
Pick whichever fits your setup:
Nuxt/SSR: Wrap formatted dates in
<ClientOnly>:vue<template> <ClientOnly> <span>{{ adapter.format(date, 'fullDate') }}</span> </ClientOnly> </template>Vue SSR: Defer formatting until after hydration:
vue<script setup lang="ts"> import { useDate } from '@vuetify/v0' import { shallowRef, onMounted, computed } from 'vue' const { adapter } = useDate() const isMounted = shallowRef(false) const date = adapter.date('2024-06-15T10:30:00') onMounted(() => { isMounted.value = true }) const formatted = computed(() => isMounted.value ? adapter.format(date, 'fullDate') : date?.toString() )) </script>Server timezone: Set
TZ=UTCenvironment variable on your server for consistent baseline.
Only if a runtime you target lacks native Temporal. V0DateAdapter prefers the runtime’s native implementation and falls back to @js-temporal/polyfill↗︎ when it’s missing — once every target ships native Temporal, the polyfill is no longer required.
Yes. The adapter pattern decouples date operations from the library — extend DateAdapter<T> (the page’s DateFnsAdapter shows the shape) and pass it as the adapter option to createDatePlugin. Only V0DateAdapter ships built-in; other libraries need a custom adapter.
format() takes a named preset (fullDate, shortDate, monthAndYear, …) and is locale-aware. formatByString() takes an explicit token string (YYYY-MM-DD, HH:mm, …) for exact, hand-built output. Reach for presets first; drop to tokens when you need a specific layout.
Uses native Temporal when the runtime provides it; otherwise requires the @js-temporal/polyfill↗︎ optional peer. Install with
pnpm add @js-temporal/polyfill. ↩︎
Benchmarks
Every operation is profiled across multiple dataset sizes to measure real-world throughput. Each benchmark is assigned a performance tier—good, fast, blazing, or slow—and groups are scored by averaging their individual results so you can spot bottlenecks at a glance. This transparency helps you make informed decisions about which patterns scale for your use case. Learn more in the benchmarks guide.