Skip to main content
You are viewing Pre-Alpha documentation.
Vuetify0 Logo
Theme
Mode
Accessibility
Vuetify

Sign in

Sign in with your preferred provider to access your account.

useDate

The useDate composable provides comprehensive date manipulation capabilities using the adapter pattern. The default adapter uses the Temporal API↗ for modern, immutable date operations with locale-aware formatting via Intl.DateTimeFormat. Integrates with useLocale for automatic locale synchronization.


Intermediate100% coverageBlazing FastFeb 4, 2026

Installation

The built-in Vuetify0DateAdapter requires the @js-temporal/polyfill package:

bash
pnpm add @js-temporal/polyfill
Tip

The Temporal API is a Stage 3 TC39 proposal↗. Once browsers ship native support, the polyfill will no longer be required.

Then install the date plugin with an adapter:

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

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

The adapter option is required. The Vuetify0DateAdapter 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: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>

API Reference

The following API details are for the useDate composable.

Functions

createDate

(options: DateOptions<Z>) => E

Creates a new date context.

createDateContext

(options: DateContextOptions<Z>) => ContextTrinity<E>

Creates a new date context trinity.

createDatePlugin

(options: DatePluginOptions<Z>) => any

Creates a new date plugin.

useDate

(namespace?: string) => E

Returns the current date context. Requires `createDatePlugin` to be installed with an adapter.

Options

adapter required

DateAdapter<Z>

Date adapter instance.

locale

string

Locale for formatting (defaults to useLocale's selected locale or 'en-US')

locales

Record<string, string>

Short locale codes mapped to full Intl locale strings (e.g., { en: 'en-US' })

Properties

adapter

DateAdapter<Z>

The date adapter instance

locale

ComputedRef<string>

Current locale (reactive, synced with useLocale if available)

DateAdapter Interface

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

ts
interface DateAdapter<T> {
  locale?: string

  // Construction & Conversion
  date (value?: unknown): T | null
  toJsDate (value: T): Date
  parseISO (dateString: string): T
  toISO (date: T): string
  parse (value: string, format: string): T | null
  isValid (date: unknown): date is T  // Type predicate
  isNull (value: T | null): value is null  // Type predicate

  // Formatting
  format (date: T, formatString: string): string
  formatByString (date: T, formatString: string): string
  formatNumber (numberToFormat: string): string
  getFormatHelperText (format: string): string
  getMeridiemText (ampm: 'am' | 'pm'): string

  // Navigation
  startOfDay (date: T): T
  endOfDay (date: T): T
  startOfWeek (date: T, firstDayOfWeek?: number): T
  endOfWeek (date: T, firstDayOfWeek?: number): T
  startOfMonth (date: T): T
  endOfMonth (date: T): T
  startOfYear (date: T): T
  endOfYear (date: T): T

  // Arithmetic
  addSeconds (date: T, amount: number): T
  addMinutes (date: T, amount: number): T
  addHours (date: T, amount: number): T
  addDays (date: T, amount: number): T
  addWeeks (date: T, amount: number): T
  addMonths (date: T, amount: number): T
  addYears (date: T, amount: number): T

  // Comparison
  isAfter (date: T, comparing: T): boolean
  isAfterDay (date: T, comparing: T): boolean
  isAfterMonth (date: T, comparing: T): boolean
  isAfterYear (date: T, comparing: T): boolean
  isBefore (date: T, comparing: T): boolean
  isBeforeDay (date: T, comparing: T): boolean
  isBeforeMonth (date: T, comparing: T): boolean
  isBeforeYear (date: T, comparing: T): boolean
  isEqual (date: T, comparing: T): boolean
  isSameDay (date: T, comparing: T): boolean
  isSameHour (date: T, comparing: T): boolean
  isSameMonth (date: T, comparing: T): boolean
  isSameYear (date: T, comparing: T): boolean
  isWithinRange (date: T, range: [T, T]): boolean

  // Getters
  getYear (date: T): number
  getMonth (date: T): number  // 0-indexed
  getDate (date: T): number
  getHours (date: T): number
  getMinutes (date: T): number
  getSeconds (date: T): number
  getDiff (date: T, comparing: T | string, unit?: string): number
  getWeek (date: T, firstDayOfWeek?: number, minimalDays?: number): number
  getDaysInMonth (date: T): number

  // Setters (immutable - returns new instance)
  setYear (date: T, year: number): T
  setMonth (date: T, month: number): T  // 0-indexed
  setDate (date: T, day: number): T
  setHours (date: T, hours: number): T
  setMinutes (date: T, minutes: number): T
  setSeconds (date: T, seconds: number): T

  // Calendar Utilities
  getWeekdays (firstDayOfWeek?: number, format?: 'long' | 'short' | 'narrow'): string[]
  getWeekArray (date: T, firstDayOfWeek?: number): T[][]
  getMonthArray (date: T): T[]
  getYearRange (start: T, end: T): T[]
  getNextMonth (date: T): T
  getPreviousMonth (date: T): T

  // Utility
  mergeDateAndTime (date: T, time: T): T
  getCurrentLocaleCode (): string
  is12HourCycleInCurrentLocale (): boolean
}

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

Examples

The following examples demonstrate common date operations using the default Temporal adapter:

January 1970
S
M
T
W
T
F
S
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<script setup lang="ts">
  import { useDate } from '@vuetify/v0'
  import { computed, shallowRef } from 'vue'

  const { adapter } = useDate()

  const current = shallowRef(adapter.date()!)
  const weekdays = computed(() => adapter.getWeekdays(0, 'narrow'))
  const weeks = computed(() => {
    const allWeeks = adapter.getWeekArray(current.value)
    // Always show exactly 5 weeks for consistent height
    if (allWeeks.length >= 5) return allWeeks.slice(0, 5)
    // Pad with next month's week if only 4 weeks (e.g., Feb 2025)
    const nextMonth = adapter.getNextMonth(current.value)
    const nextWeeks = adapter.getWeekArray(nextMonth)
    return [...allWeeks, nextWeeks[1]].slice(0, 5)
  })
  const monthYear = computed(() => adapter.format(current.value, 'monthAndYear'))

  function prev () {
    current.value = adapter.getPreviousMonth(current.value)
  }

  function next () {
    current.value = adapter.getNextMonth(current.value)
  }

  function isToday (date: typeof current.value) {
    const today = adapter.date()
    return today ? adapter.isSameDay(date, today) : false
  }

  function isCurrentMonth (date: typeof current.value) {
    return adapter.isSameMonth(date, current.value)
  }
</script>

<template>
  <div class="w-64 mx-auto">
    <div class="flex items-center justify-between mb-2 px-2">
      <button
        class="p-1 rounded hover:bg-surface-tint"
        type="button"
        @click="prev"
      >
        &larr;
      </button>
      <span class="font-semibold text-sm">{{ monthYear }}</span>
      <button
        class="p-1 rounded hover:bg-surface-tint"
        type="button"
        @click="next"
      >
        &rarr;
      </button>
    </div>

    <div class="grid grid-cols-7 gap-px text-center text-xs">
      <div
        v-for="day in weekdays"
        :key="day"
        class="p-1 font-medium opacity-60"
      >
        {{ day }}
      </div>

      <template v-for="(week, i) in weeks" :key="i">
        <div
          v-for="(date, j) in week"
          :key="j"
          class="p-1 rounded"
          :class="{
            'bg-primary text-on-primary': isToday(date),
            'opacity-40': !isCurrentMonth(date),
          }"
        >
          {{ adapter.getDate(date) }}
        </div>
      </template>
    </div>
  </div>
</template>

Locale Integration

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

src/main.ts
import { createApp } from 'vue'
import { Vuetify0DateAdapter } 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 Vuetify0DateAdapter(),
    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.

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 type { DateAdapter } from '@vuetify/v0'
import { isValid as dateFnsIsValid, parseISO, format as dateFnsFormat } from 'date-fns'

class DateFnsAdapter implements 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 isNull methods are type predicates. This enables TypeScript to narrow types after validation:

ts
const date = adapter.date(input)
if (!adapter.isNull(date) && adapter.isValid(date)) {
  // TypeScript knows `date` is Date here
  adapter.format(date, 'fullDate')
}

Known Limitations

  • parse() format parameter: The parse() method’s format parameter is currently ignored. The Temporal API doesn’t provide built-in format parsing. 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.

SSR and Hydration

Warning

Date formatting can cause hydration mismatches in SSR applications. Server and client environments may produce different formatted output due to timezone differences.

SSR Behavior for adapter.date():

  • Browser: Returns current time via Temporal.Now.plainDateTimeISO()

  • Server: Returns epoch (1970-01-01T00:00:00) for deterministic rendering

This is intentional to prevent hydration mismatches. For SSR apps needing current time, pass Date.now() explicitly.

Timezone-dependent formatting: Intl.DateTimeFormat uses the system timezone. Server environments (often UTC) and client browsers (user’s local timezone) produce different formatted strings.

Solutions:

  1. Nuxt/SSR: Wrap formatted dates in <ClientOnly>:

    vue
    <template>
      <ClientOnly>
       <span>{{ adapter.format(date, 'fullDate') }}</span>
     </ClientOnly>
    </template>
  2. 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>
  3. Server timezone: Set TZ=UTC environment variable on your server for consistent baseline

Reactivity

The date context provides minimal reactivity, with the adapter being a static instance.

PropertyReactiveNotes
localeComputed from useLocale if available
adapterStatic adapter instance

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?

© 2016-1970 Vuetify, LLC
Ctrl+/