JS 获取当前日期并格式化为 YYYY-MM-DD

作者:小满

时间:2026-11-02

浏览:538

详细讲解在 JavaScript 中获取当前日期并格式化为 YYYY-MM-DD 字符串的常用方法,包括基于 Date 对象的 padStart 补零拼接、现代 Intl.DateTimeFormat API 以及处理 toISOString 时区陷阱的正确方案。

文章目录
获取当前日期并输出为 YYYY-MM-DD 格式的最稳妥方案,是通过 new Date() 提取本地年月日数字,再利用 String.prototype.padStart() 对单数月份和日期前置补零后拼接。该方法直接使用系统本地时区,不依赖第三方库,且避开了 UTC 转换引发的隔日偏差。
JS 获取当前日期并格式化为 YYYY-MM-DD
图 1:YYYY-MM-DD 结构拆解与目标格式示意

一、推荐做法:基于 padStart 的三步格式化

在现代 JavaScript(ES2017+)环境中,最通用的格式化方式是先通过 Date 实例的方法提取本地年、月、日,再将不足两位的月和日补齐前导零。

// 1. 获取当前时间实例
const now = new Date();

// 2. 提取年、月、日,并对月和日补零
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');

// 3. 模板字面量拼接
const formattedDate = `${year}-${month}-${day}`;

console.log(formattedDate); // 示例输出:"2026-11-02"

该方案由三个关键动作组成:

  1. 使用 getFullYear():返回四位数的公历年份(例如 2026)。切勿使用已废弃的 getYear(),后者返回的是相对 1900 年的差值。
  2. 月份需要加 1:JavaScript 中 getMonth() 的返回值从 0(一月)到 11(十二月),因此真实月份必须显式 + 1。
  3. 使用 padStart(2, '0') 补零:padStart 是字符串原型方法,作用是当字符串长度不足目标位数时,在左侧填充指定字符。因此先用 String() 转为字符串,再进行补位。如果月份是 5,补位后即为 "05";如果是 11,长度已达到 2,保持原样。
JS 获取当前日期并格式化为 YYYY-MM-DD
图 2:原生 Date 提取、补零与字符模板拼接的数据流转流程

二、关键陷阱:为什么慎用 toISOString().slice(0, 10)

网络上常能见到一种极简写法:new Date().toISOString().slice(0, 10),或者使用 split('T')[0]。这种写法虽然只有一行,但在非零时区(例如中国的东八区 UTC+8)存在严重的隔日偏差问题。

时区偏差成因:Date.prototype.toISOString() 总是返回以 UTC 零时区为基准的 ISO 8601 字符串(末尾带有字母 Z)。

假设在北京时间 2026 年 11 月 2 日清晨 06:30:00 执行代码:

  • 北京时间为 UTC+8,时间是 2026-11-02 06:30:00。
  • 对应的世界协调时(UTC)需要减去 8 小时,即 2026-11-01 22:30:00Z。
  • 调用 toISOString() 得到的是 "2026-11-01T22:30:00.000Z"。
  • 截取前 10 位得到的结果是 "2026-11-01",比本地日期整整少了一天。
JS 获取当前日期并格式化为 YYYY-MM-DD
图 3:本地时间与 UTC 转换时区偏差对比(每天 00:00~08:00 执行容易出错)

三、进阶方案:使用现代 Intl.DateTimeFormat API

ECMAScript 国际化标准提供了 Intl.DateTimeFormat API。利用这个 API,可以通过指定语言区域代码(Locale)或格式部件,直接生成符合要求的日期字符串,还支持显式指定时区。

方法 1:利用加拿大英语区(en-CA)的默认 ISO 输出

在国际标准中,加拿大(en-CA)的标准短日期书写格式恰好是 YYYY-MM-DD。

const formatter = new Intl.DateTimeFormat('en-CA', {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit'
});

const formattedDate = formatter.format(new Date());
console.log(formattedDate); // 示例输出:"2026-11-02"

如果希望明确按某个特定时区(例如上海时间)格式化,即使服务器部署在 UTC 或其他时区的容器内,也可以直接传入 timeZone 参数:

const bjFormatter = new Intl.DateTimeFormat('en-CA', {
  timeZone: 'Asia/Shanghai',
  year: 'numeric',
  month: '2-digit',
  day: '2-digit'
});

console.log(bjFormatter.format(new Date())); // 始终输出上海当前日期

方法 2:使用 formatToParts 自由解构组装

如果不想依赖 en-CA 的区域习惯,可以使用 formatToParts() 方法。它将日期拆分为类型与值的对象数组,便于自由拼装:

const now = new Date();
const parts = new Intl.DateTimeFormat('zh-CN', {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit'
}).formatToParts(now);

// 将数组转为以 type 为 key 的普通对象
const { year, month, day } = Object.fromEntries(
  parts.map(p => [p.type, p.value])
);

const formattedDate = `${year}-${month}-${day}`;
console.log(formattedDate); // 示例输出:"2026-11-02"
JS 获取当前日期并格式化为 YYYY-MM-DD
图 4:Intl.DateTimeFormat 结合时区与部件格式化的工作原理

四、方案对比与选型依据

为了帮助在实际开发中做出合适的技术选型,以下将原生 padStart 拼接与 Intl.DateTimeFormat 的关键差异总结如下:

对比维度 padStart 原生拼接 Intl.DateTimeFormat
环境依赖 现代浏览器全支持,Node.js 8+ 现代浏览器全支持,Node.js 12+
执行性能 极高(简单的原生属性读取与字符操作) 中等(实例创建相对耗时,建议复用 formatter 实例)
时区控制 默认基于执行环境的本地时间 支持任意指定 IANA 时区(如 Asia/Shanghai)
语义直观度 直观、透明、易理解,符合绝大部分日常业务 配置参数丰富,适合复杂或跨国别应用
代码体积 0 依赖,仅 3~4 行代码 0 依赖,内置原生 API
JS 获取当前日期并格式化为 YYYY-MM-DD
图 5:格式化方案技术选型与避坑决策树

五、可直接复用的工具函数封装

在实际项目开发中,通常建议将日期格式化封装为一个简短的通用函数,支持传入可选的日期对象与自定义分隔符:

/**
 * 获取指定日期(默认当前时间)并格式化为 YYYY-MM-DD
 * @param {Date} [date=new Date()] 要格式化的日期实例
 * @param {string} [separator='-'] 分隔符,默认为短横线 '-'
 * @returns {string} 格式化后的日期字符串
 */
function formatDate(date = new Date(), separator = '-') {
  // 防御性校验:如果传入无效对象,自动回退到当前时间
  const d = date instanceof Date && !isNaN(date.getTime()) ? date : new Date();

  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');

  return `${year}${separator}${month}${separator}${day}`;
}

// 实际使用示例:
console.log(formatDate());               // 默认:"2026-11-02"
console.log(formatDate(new Date(), '/')); // 自定义分隔符:"2026/11/02"
console.log(formatDate(new Date(), ''));  // 无分隔符:"20261102"
注意事项: getDate() 返回的是当月的几号(1 到 31),千万不要误写成 getDay(),后者返回的是星期几(0 代表周日,1 到 6 代表周一到周六)。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章