Skip to main content
Vuetify0 is now a release candidate!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

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:

bash
pnpm add @js-temporal/polyfill
Tip

The 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:

src/plugins/zero.ts
import { V0DateAdapter } from '@vuetify/v0/date'
import { createDatePlugin } from '@vuetify/v0'

app.use(
  createDatePlugin({
    adapter: new V0DateAdapter(),
    locale: 'en-US',
  })
)
Note

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:

Locale:en-USFull date:Thursday, January 1, 1970Short date:1/1/70Weekday:ThursdayTime:12:00 AMCustom format:1970-01-01 00:00
<script setup lang="ts">
  import { useDate } from '@vuetify/v0'
  import { computed } from 'vue'

  const { adapter, locale } = useDate()

  const today = computed(() => adapter.date())
  const formatted = computed(() => today.value ? adapter.format(today.value, 'fullDate') : '')
  const shortDate = computed(() => today.value ? adapter.format(today.value, 'shortDate') : '')
  const custom = computed(() => today.value ? adapter.formatByString(today.value, 'YYYY-MM-DD HH:mm') : '')
  const weekday = computed(() => today.value ? adapter.format(today.value, 'weekday') : '')
  const time = computed(() => today.value ? adapter.format(today.value, 'fullTime12h') : '')
</script>

<template>
  <div class="flex flex-col gap-4">
    <div class="grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm">
      <span class="opacity-60">Locale:</span>
      <span class="font-mono">{{ locale }}</span>

      <span class="opacity-60">Full date:</span>
      <span class="font-semibold">{{ formatted }}</span>

      <span class="opacity-60">Short date:</span>
      <span>{{ shortDate }}</span>

      <span class="opacity-60">Weekday:</span>
      <span>{{ weekday }}</span>

      <span class="opacity-60">Time:</span>
      <span>{{ time }}</span>

      <span class="opacity-60">Custom format:</span>
      <span class="font-mono">{{ custom }}</span>
    </div>
  </div>
</template>

Adapters

Adapters let you swap the underlying date library without changing your application code.

AdapterImportDescription
V0DateAdapter@vuetify/v0/dateTemporal API↗︎ adapter[1]

DateAdapter Interface

The adapter provides a comprehensive API compatible with date-io↗︎:

ts
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:

PresetExample Output
fullDateSaturday, June 15, 2024
fullDateWithWeekdaySaturday, June 15, 2024
normalDateJun 15, 2024
shortDate6/15/24
year2024
monthJune
monthShortJun
monthAndYearJune 2024
monthAndDateJune 15
weekdaySaturday
weekdayShortSat
dayOfMonth15
hours12h10 AM
hours24h10
minutes30
seconds45
fullTime10:30:45 AM
fullTime12h10:30:45 AM
fullTime24h10:30:45
fullDateTimeSaturday, June 15, 2024 at 10:30 AM
keyboardDate06/15/2024
keyboardDateTime06/15/2024 10:30 AM

Format Tokens

The formatByString() method supports these tokens:

TokenOutputExample
YYYY4-digit year2024
YY2-digit year24
MMMMFull month nameJune
MMMShort month nameJun
MMMonth (zero-padded)06
MMonth6
ddddFull weekday nameSaturday
dddShort weekday nameSat
DDDay (zero-padded)15
DDay15
HH24-hour (zero-padded)10
H24-hour10
hh12-hour (zero-padded)10
h12-hour10
mmMinutes (zero-padded)30
mMinutes30
ssSeconds (zero-padded)45
sSeconds45
AAM/PMAM
aam/pmam

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:

Adapter Pattern Flow

Use controls to zoom and pan. Click outside or press Escape to close.

Adapter Pattern Flow

Create custom adapters for different date libraries (date-fns, luxon, dayjs):

src/adapters/date-fns-adapter.ts
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(),
  })
)
Tip

The isValid and isNullish methods are type predicates. This enables TypeScript to narrow types after validation:

ts
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.

PropertyReactiveNotes
localeComputed from useLocale if available
adapterStatic adapter instance

Examples

The following example builds a complete, interactive date surface from adapter calls alone — no DatePicker component required.

Interactive month calendar

A navigable month grid with click-to-select, built entirely from the adapter. useCalendar.ts calls useDate() once and owns all the date math: getWeekArray() produces the 2D week grid, getWeekdays('narrow') drives the column headers, getPreviousMonth() and getNextMonth() handle navigation, and isSameDay() / isSameMonth() power the today ring, the selected fill, and the greyed-out overflow cells. The grid renders as many week rows as the month spans — four to six — straight from getWeekArray(), so every in-month day stays visible and the calendar never truncates a long month or borrows days from the wrong neighbouring week.

The composable precomputes each weeks cell into a flat { date, day, today, selected, outside } record, so CalendarGrid.vue renders the surface from plain props — weekdays, weeks, monthYear, plus the prev, next, today, and select callbacks — without ever touching the adapter directly. The entry instantiates the calendar once and reads selectedLabel and locale for the summary panel. This is the structural half of the adapter interface — building and navigating grids — rather than the formatting presets shown in the Usage example above.

Reach for this pattern when building a DatePicker, DateRangePicker, or any calendar surface where the adapter should own the grid layout. The adapter is locale-aware by default: getWeekdays and the month name both respond to the locale set at plugin install time, so switching the active locale via useLocale reformats the calendar with no extra code. See the locale integration section below for how the two plugins sync.

FileRole
useCalendar.tsWraps useDate(); owns month/selection state and exposes weekday labels, precomputed week cells, and navigation callbacks
CalendarGrid.vueRenders the weekday headers and day buttons from its props; styles today, selected, and outside-month cells via data attributes
month-calendar.vueEntry point — instantiates the calendar, wires it to the grid, and shows the selected date and active locale
January 1970
S
M
T
W
T
F
S
SelectedThursday, January 1, 1970
en-US

Recipes

Locale Integration

When useLocale is available, useDate automatically syncs with the selected locale:

src/main.ts
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

Discord
Need help? Join our community for support and discussions ↗

API Reference

The following API details are for the useDate composable.

  1. 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.

View benchmark source↗

Was this page helpful?

Ctrl+/