先记住这个答案
<input type="date"> 提交的值是一个符合 yyyy-mm-dd 格式的字符串,例如 2025-03-14。该值只包含年、月、日信息,不包含时区偏移或 UTC 指示。浏览器根据用户本地化界面选择日期后,内部统一转换为这种无时区的日期字符串。通过 value 属性或表单提交都能获得该格式,valueAsNumber 则返回对应 UTC 午夜的时间戳。
- 提交值为
yyyy-mm-dd字符串 - 值本身不包含时区信息
- 显示格式与提交值可能不同
值格式与规范化机制
date 输入类型的 value 属性是一个字符串,严格遵循 yyyy-mm-dd 格式,其中 yyyy 为四位年份,mm 为两位月份(01-12),dd 为两位日(01-31)。即便浏览器根据用户区域把界面显示成 dd/mm/yyyy 或 mm/dd/yyyy,提交的数据与 value 属性始终保持为 yyyy-mm-dd。
当你在 JavaScript 中读取 input.value 时,得到的正是这种格式化字符串;写入时也必须采用该格式,否则会被视为空值。valueAsNumber 属性将日期解释为 UTC 时间戳,即该日期在 1970-01-01T00:00:00Z 至当天午夜之间经过的毫秒数,但 value 字符串本身不含任何 Z 或时区偏移。
航班日期筛选中的时区陷阱
假设你在开发一个国际航班搜索表单,出发日期使用 <input type="date" name="departure">。用户在东京时区选择 2026-07-20,提交后到服务端(位于 UTC 时区)收到的是 departure=2026-07-20。若盲目用 new Date("2026-07-20") 解析,JavaScript 会将其当作 UTC 午夜,导致在东京时区显示为 2026-07-20 09:00,但在洛杉矶显示为前一天的傍晚。
正确做法是把日期字符串视为“日历日期”,不要自动附加时区。当你需要用于计算时长或比较时,应显式指定时区,例如用 new Date(2026, 6, 20) 在本地时区创建日期,或使用专门的日期库。服务端收到 yyyy-mm-dd 后,通常按业务规则保留日期,不转换为 UTC 时间,除非需要与带时间的记录关联。
格式与约束的失效边界
若用户浏览器不支持 date 类型(极少数旧浏览器),控件会回退为文本输入框,用户可能输入任意格式,此时 value 不一定符合 yyyy-mm-dd,浏览器也不做自动校验。因此依赖前端格式前,必须检查 input.type 是否为 date,或者使用 feature detection。
即使浏览器支持,用户仍可能通过开发者工具修改 value 属性注入非法字符串(如 2025-13-01)。此时 value 返回原非法值,表单约束校验失败,但 valueAsNumber 返回 NaN。服务端绝不能信任前端,必须再次校验格式并检查月份范围,否则会解析出错误日期或引发异常。
容易答错的地方
- 误以为值包含时区
date的提交值从不含Z或+08:00等后缀。它只是日历日期,与时间无关。若需要结合特定时区,应使用datetime-local或单独传递时区参数。- 用本地时间 new Date(string)
- 直接
new Date("2026-07-20")在 JavaScript 中被解析为 UTC 午夜,而非本地午夜。区分不同时区的用户时容易产生偏差,应先明确日期的语义是纯日历日期。
面试官还会怎么问?
valueAsNumber 返回的时间戳是基于哪个时区?
始终基于 UTC 午夜。例如 2026-07-20 对应 2026-07-20T00:00:00Z 的时间戳。这为跨时区比较提供了固定的基准点,但进行显示时需要转换到用户本地时区。
如何手动设置或读取日期值?
通过 input.value = "2026-07-20" 设置;读取 input.value 得到 "2026-07-20"。读取 input.valueAsNumber 得到 1784505600000(示例)。注意设置非法格式时 value 变为空串。
max 和 min 属性如何处理时区?
min 与 max 属性同样是 yyyy-mm-dd 字符串,比较基于日历日期,不涉及时区。浏览器在本地日界上按日粒度限制可选择范围,但不会因为用户时区改变上下限。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。