---
title: "Date 日期时间"
description: "afz.calendarDate() 等到日期选择、输入与 ISO 字符串控件的映射。"
seo_title: "Date & Time Field"
seo_description: "How Zod date fields map to AutoForm controls — date picker, date range, date input, time input and ISO format strings, built on @internationalized/date."
canonical_url: "https://nuxt.mhaibaraai.cn/docs/auto-form/date"
---
# Date 日期时间

> afz.calendarDate() 等到日期选择、输入与 ISO 字符串控件的映射。

> \[\!TIP\]
> See: /docs/composables/use-date-formatter
> 
> useDateFormatter 文档：基于 @internationalized/date 的日期格式化和处理工具。

使用 `afz.calendarDate()` 创建日期字段，基于 [`@internationalized/date`](https://react-spectrum.adobe.com/internationalized/date/index.html){rel="[\"nofollow\"]"} 提供强大的日期处理能力：

## 日期选择器

> \[\!NOTE\]
> See: https://ui.nuxt.com/docs/components/calendar
> 
> Calendar 组件文档

单日期选择，支持日期格式化和验证：

```vue [AutoFormFieldDatePickerExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'
import { CalendarDate } from '@internationalized/date'

const { afz } = useAutoForm()
const toast = useToast()
const formatter = useDateFormatter()

const schema = afz.object({
  appointmentDate: afz.calendarDate({ controlProps: { labelFormat: 'iso' } })
    .refine(
      date => date > new CalendarDate(2026, 1, 1),
      { message: '日期必须在 2026 年之后' }
    )
    .transform(date => formatter.toTimestamp(date))
    .meta({ label: '预约日期', description: '请选择一个在 2026 年之后的日期' })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## 日期范围

日期范围选择，设置 `controlProps.range: true`：

```vue [AutoFormFieldDateRangeExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  vacation: afz.calendarDate({
    controlProps: {
      labelFormat: 'iso',
      range: true,
      valueFormat: 'iso',
      numberOfMonths: 2
    }
  })
    .meta({
      label: '日期范围',
      hint: '选择日期范围，显示两个月'
    })
})
type Schema = z.output<typeof schema>

async function onSubmit(event: FormSubmitEvent<Schema>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## 日期输入框

> \[\!NOTE\]
> See: https://ui.nuxt.com/docs/components/input-date
> 
> InputDate 组件文档

使用 `afz.inputDate()` 创建日期输入框，基于 `UInputDate` 组件提供原生的日期输入体验。

### 单日期输入

简洁的日期输入框，适合表单填写场景：

```vue [AutoFormFieldInputDateExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()
const formatter = useDateFormatter()

const schema = afz.object({
  birthDate: afz.inputDate()
    .transform(date => formatter.convertToISO(date))
    .meta({
      label: '出生日期',
      description: '使用日期输入框选择您的出生日期'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

### 日期范围输入

支持范围选择的日期输入框：

```vue [AutoFormFieldInputDateRangeExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()
const formatter = useDateFormatter()

const schema = afz.object({
  eventPeriod: afz.inputDate({
    controlProps: {
      range: true
    }
  })
    .transform(date => formatter.convertToISO(date))
    .meta({
      label: '活动周期',
      hint: '选择活动的起止日期'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## 时间输入框

使用 `afz.inputTime()` 创建时间输入框，返回 `Time` 类型（来自 `@internationalized/date`）：

> \[\!NOTE\]
> See: https://ui.nuxt.com/docs/components/input-time
> 
> InputTime 组件文档

```vue [AutoFormFieldInputTimeExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  meetingTime: afz.inputTime()
    .refine(
      time => time.hour >= 9 && time.hour < 18,
      { message: '会议时间必须在工作时间内 (9:00-18:00)' }
    )
    .transform(time => `${String(time.hour).padStart(2, '0')}:${String(time.minute).padStart(2, '0')}`)
    .meta({
      label: '会议时间',
      description: '请选择会议时间（工作时间内）'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## ISO 格式字符串

对于需要 ISO 标准格式字符串的场景，提供三种工厂方法：

- `afz.isoDate()` \- 验证 `YYYY-MM-DD` 格式
- `afz.isoTime()` \- 验证 `HH:MM[:SS[.s+]]` 格式
- `afz.isoDatetime()` \- 验证 ISO 8601 完整格式

```vue [AutoFormFieldIsoExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  scheduledDate: afz.isoDate()
    .meta({
      label: '计划日期',
      description: '输入 ISO 格式日期 (YYYY-MM-DD)',
      hint: '例如: 2025-12-31'
    }),
  scheduledTime: afz.isoTime()
    .meta({
      label: '计划时间',
      description: '输入 ISO 格式时间 (HH:MM:SS)',
      hint: '例如: 14:30:00'
    }),
  createdAt: afz.isoDatetime()
    .optional()
    .meta({
      label: '创建时间',
      description: '输入 ISO 8601 完整时间戳',
      hint: '例如: 2025-12-31T14:30:00Z'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```


## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
