useDateFormatter
基于 @internationalized/date 的日期格式化和处理工具。
用法
使用自动导入的 useDateFormatter composable 进行日期格式化、转换和操作,基于 @internationalized/date 库实现国际化日期处理。
<script setup lang="ts">
const formatter = useDateFormatter({ locale: 'zh-CN' })
const today = formatter.getToday()
const formattedDate = formatter.format(today)
// "2025年11月29日"
const isoString = formatter.toISO(today)
// "2025-11-29"
</script>
useDateFormatter基于Intl.DateTimeFormat提供本地化日期格式化。- 支持单个日期、日期范围、日期数组以及嵌套对象的批量转换。
- 通过
timeZone选项指定时区(默认本地时区),标识符遵循 IANA 时区数据库规范。
所有格式化和转换方法都内置了错误处理,当传入
null 或 undefined 时会返回空字符串或 null,避免抛出异常。能力一览
下表覆盖了 useDateFormatter 在常用日期场景下的输出形态:
当前 locale: zh-CN · timeZone: UTC
| 调用 | 返回值 |
|---|---|
format(today) | 2026年6月21日 |
toISO(today) | 2026-06-21 |
toTimestamp(today) | 1782000000000 |
toUnixTimestamp(today) | 1782000000 |
isWeekend(today) | true |
isWeekday(today) | false |
isToday(today) | true |
getDayOfWeek(today) | 6 |
getDayOfWeekName(today, "long") | 星期日 |
getDayOfWeekName(today, "short") | 周日 |
getStartOfMonth(today) | 2026-06-01 |
getEndOfMonth(today) | 2026-06-30 |
getStartOfYear(today) | 2026-01-01 |
getEndOfYear(today) | 2026-12-31 |
formatRange(start, end) | 2026年6月21日 - 2026年6月28日 |
formatArray([d, d+1, d+2]) | 2026年6月21日, 2026年6月22日, 2026年6月23日 |
parse("2026-01-01")?.toString() | 2026-01-01 |
<script setup lang="ts">
const f = useDateFormatter({ locale: 'zh-CN' })
const today = f.getToday()
const range = { start: today, end: today.add({ days: 7 }) }
const list = [today, today.add({ days: 1 }), today.add({ days: 2 })]
const rows = [
{ method: 'format(today)', value: f.format(today) },
{ method: 'toISO(today)', value: f.toISO(today) },
{ method: 'toTimestamp(today)', value: f.toTimestamp(today) },
{ method: 'toUnixTimestamp(today)', value: f.toUnixTimestamp(today) },
{ method: 'isWeekend(today)', value: f.isWeekend(today) },
{ method: 'isWeekday(today)', value: f.isWeekday(today) },
{ method: 'isToday(today)', value: f.isToday(today) },
{ method: 'getDayOfWeek(today)', value: f.getDayOfWeek(today) },
{ method: 'getDayOfWeekName(today, "long")', value: f.getDayOfWeekName(today, 'long') },
{ method: 'getDayOfWeekName(today, "short")', value: f.getDayOfWeekName(today, 'short') },
{ method: 'getStartOfMonth(today)', value: f.toISO(f.getStartOfMonth(today)) },
{ method: 'getEndOfMonth(today)', value: f.toISO(f.getEndOfMonth(today)) },
{ method: 'getStartOfYear(today)', value: f.toISO(f.getStartOfYear(today)) },
{ method: 'getEndOfYear(today)', value: f.toISO(f.getEndOfYear(today)) },
{ method: 'formatRange(start, end)', value: f.formatRange(range.start, range.end) },
{ method: 'formatArray([d, d+1, d+2])', value: f.formatArray(list) },
{ method: 'parse("2026-01-01")?.toString()', value: f.parse('2026-01-01')?.toString() ?? 'null' }
]
const columns = [
{ accessorKey: 'method', header: '调用' },
{ accessorKey: 'value', header: '返回值' }
]
</script>
<template>
<div class="flex flex-col gap-3">
<p class="text-xs text-muted">
当前 locale: {{ f.locale }} · timeZone: {{ f.timeZone }}
</p>
<MDataTable :columns="columns" :data="rows" stripe bordered density="compact" />
</div>
</template>
与 AutoForm 集成
在 AutoForm 中使用日期字段时,建议使用 convertToISO() 进行批量转换后提交:
<script setup lang="ts">
const { afz } = useAutoForm()
const formatter = useDateFormatter()
const schema = afz.object({
eventDate: afz.calendarDate(),
eventRange: afz.calendarDate({
controlProps: { mode: 'range' }
})
})
const formData = ref()
async function handleSubmit() {
// 自动处理所有日期字段的转换
const payload = formatter.convertToISO(formData.value)
// payload.eventDate: "2025-11-29"
// payload.eventRange: { start: "2025-11-01", end: "2025-11-30" }
await api.submit(payload)
}
</script>
convertToISO 自动遍历所有嵌套日期字段并保持对象结构不变,无需手动转换。API
useDateFormatter()
useDateFormatter(options?: DateFormatterOptions): DateFormatter
创建日期格式化器实例。
Parameters
options
DateFormatterOptions
日期格式化配置选项。
locale
string
语言区域,默认
'zh-CN'。formatOptions
Intl.DateTimeFormatOptions
日期格式化选项,遵循 Intl.DateTimeFormat 规范。默认为
{ dateStyle: 'medium' }。timeZone
string
Returns
返回包含以下方法和属性的日期格式化器对象。
格式化方法
format()
(date: DateValue | undefined | null) => string
格式化单个日期为本地化字符串。
formatter.format(date)
// "2025年11月29日"
formatRange()
(start: DateValue | undefined | null, end: DateValue | undefined | null, separator?: string) => string
格式化日期范围,默认分隔符为
' - '。formatter.formatRange(startDate, endDate)
// "2025年11月1日 - 2025年11月30日"
formatter.formatRange(startDate, endDate, ' 至 ')
// "2025年11月1日 至 2025年11月30日"
formatArray()
(dates: DateValue[] | undefined | null, separator?: string) => string
格式化日期数组,默认分隔符为
', '。formatter.formatArray([date1, date2, date3])
// "2025年11月1日, 2025年11月15日, 2025年11月29日"
转换方法
toISO()
(date: DateValue | undefined | null) => string
转换为 ISO 8601 字符串。
formatter.toISO(date)
// "2025-11-29"
toDate()
(date: DateValue | undefined | null) => Date | null
转换为 JavaScript Date 对象。
toTimestamp()
(date: DateValue | undefined | null) => number | null
转换为时间戳(毫秒)。
formatter.toTimestamp(date)
// 1732838400000
toUnixTimestamp()
(date: DateValue | undefined | null) => number | null
转换为 Unix 时间戳(秒)。
formatter.toUnixTimestamp(date)
// 1732838400
parse()
(value: string) => DateValue | null
解析 ISO 8601 日期字符串。自动识别
CalendarDate、CalendarDateTime 或 ZonedDateTime。formatter.parse('2025-11-29')
// CalendarDate
formatter.parse('2025-11-29T10:30:00')
// CalendarDateTime
formatter.parse('2025-11-29T10:30:00[Asia/Shanghai]')
// ZonedDateTime
工具方法 - 获取日期
getToday()
() => CalendarDate
获取今天的日期。
getNow()
() => ZonedDateTime
获取当前日期时间。
getStartOfWeek()
(date: DateValue) => DateValue
获取一周的开始日期(基于当前语言区域)。
getEndOfWeek()
(date: DateValue) => DateValue
获取一周的结束日期(基于当前语言区域)。
getStartOfMonth()
(date: DateValue) => DateValue
获取一月的开始日期。
getEndOfMonth()
(date: DateValue) => DateValue
获取一月的结束日期。
getStartOfYear()
(date: DateValue) => DateValue
获取一年的开始日期。
getEndOfYear()
(date: DateValue) => DateValue
获取一年的结束日期。
工具方法 - 查询
getDayOfWeek()
(date: DateValue) => number
获取星期几数字(0-6,0 为本地化的一周第一天)。
getDayOfWeekName()
(date: DateValue, style?: 'narrow' | 'short' | 'long') => string
获取本地化的星期几名称。
Parameters
date
DateValue required
日期对象。
style
'narrow' | 'short' | 'long'
格式样式。 默认
long'narrow'- 最短格式,如「一」'short'- 短格式,如「周一」'long'- 完整格式,如「星期一」
const date = formatter.getToday()
formatter.getDayOfWeekName(date, 'narrow') // "一"
formatter.getDayOfWeekName(date, 'short') // "周一"
formatter.getDayOfWeekName(date, 'long') // "星期一"
formatter.getDayOfWeekName(date) // "星期一" (默认)
getWeeksInMonth()
(date: DateValue) => number
获取本月的周数。
isWeekday()
(date: DateValue) => boolean
判断是否为工作日。
isWeekend()
(date: DateValue) => boolean
判断是否为周末。
isSameDay()
(a: DateValue, b: DateValue) => boolean
判断是否为同一天。
isSameMonth()
(a: DateValue, b: DateValue) => boolean
判断是否为同一月。
isSameYear()
(a: DateValue, b: DateValue) => boolean
判断是否为同一年。
isToday()
(date: DateValue) => boolean
判断是否为今天。
isDateValue()
(value: unknown) => value is DateValue
类型守卫,判断是否为
DateValue 类型。isDateRange()
(value: unknown) => value is DateRange
类型守卫,判断是否为
DateRange 类型。批量转换方法
convertData()
<T>(data: T, converter: (value: DateValue) => any) => T
通用数据转换函数,自动处理单个日期、日期范围、日期数组以及嵌套对象。
const converted = formatter.convertData(complexData, formatter.toISO)
convertToISO()
<T>(data: T) => T
批量转换为 ISO 字符串。支持单个日期、日期范围、数组和嵌套对象。
// 单个日期
formatter.convertToISO(date)
// "2025-11-29"
// 日期范围
formatter.convertToISO({ start: date1, end: date2 })
// { start: "2025-11-01", end: "2025-11-30" }
// 日期数组
formatter.convertToISO([date1, date2])
// ["2025-11-01", "2025-11-15"]
// 嵌套对象
formatter.convertToISO({
createdAt: date1,
range: { start: date2, end: date3 }
})
// {
// createdAt: "2025-11-01",
// range: { start: "2025-11-20", end: "2025-11-29" }
// }
convertToFormatted()
<T>(data: T) => T
批量转换为格式化字符串。
convertToDate()
<T>(data: T) => T
批量转换为 Date 对象。
配置属性
locale
string
当前使用的语言区域。
timeZone
string
当前使用的时区。
Changelog
No recent changes