当前位置:首页 > 云服务器 > 正文

JS时间格式化怎么写?时间和日期格式化函数有哪些?

JavaScript时间格式化没有内置的万能方法,但通过Date对象结合padStart补零、toLocaleString本地化或自定义封装函数,可以在几行代码内实现任意格式的日期时间输出。无论是前端展示“2026-03-18 14:30:00”还是后端日志的“2026/03/18 14:30:00.123”,掌握核心思路后,你甚至可以脱离第三方库,手写一个轻量级格式化工具。

先理解JS时间格式化的三个底层抓手

日常开发中,我们面对的无非是三类需求:固定格式输出本地化语言显示相对时间计算,这三类需求分别对应三种原生能力。

Date对象的基础方法:所有格式化的起点

new Date()返回一个对象,它提供了getFullYear()、getMonth()、getDate()、getHours()、getMinutes()、getSeconds()、getMilliseconds()等基础方法,注意两个坑:getMonth()从0开始,所以月份必须加1;getDay()返回星期几,0代表周日。

这里给出一个最基础的格式化函数,相当于“手搓”一个format:

function formatDate(date, fmt) { const o = { 'y+': date.getFullYear(), 'M+': date.getMonth() + 1, 'd+': date.getDate(), 'H+': date.getHours(), 'm+': date.getMinutes(), 's+': date.getSeconds(), 'S': date.getMilliseconds() }; for (let k in o) { if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : String(o[k]).padStart(2, '0')); } } return fmt; } // 调用示例 console.log(formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss')); // 2026-03-18 14:30:00

这段代码的关键在于正则匹配yyyy、MM等占位符,然后用padStart补零。padStart(2, '0')是ES2017标准方法,兼容性早已覆盖所有现代浏览器。

toLocaleString的本地化魔法:适合快速输出

如果不需要精确控制格式,toLocaleString是最省事的方案,它支持locale参数和options对象:

const now = new Date(); console.log(now.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false })); // 输出:2026/03/18 14:30:00

hour12: false强制24小时制,但注意不同浏览器对locale的解析存在细微差异,比如某些版本会输出“2026/03/18 14:30:00”,而另一些则输出“2026-03-18 14:30:00”,如果你追求跨端一致性,建议还是用第一个方案。

时间戳与ISO字符串:格式化前的数据来源

几乎所有格式化操作都始于以下三种数据:

  • Date.now():返回当前时间戳(毫秒)
  • new Date('2026-03-18T14:30:00.000Z')

    :解析ISO 8601字符串

  • new Date(2026, 2, 18):本地时间构造(注意月份从0开始)

实际项目中,后端接口经常返回时间戳或UTC字符串,你需要先转换为Date对象,再调用格式化函数,一个常见坑是IOS设备对new Date('2026-03-18 14:30:00')不兼容,必须把空格替换为T。

JS时间格式化怎么写?时间和日期格式化函数有哪些? 第1张

封装一个生产级格式化函数:从基础到进阶

工作中我们很少直接裸写Date方法,而是封装工具函数,下面这套方案兼顾了可扩展性和容错性。

参数归一化:处理时间戳、字符串、Date对象

用户可能传入任何类型,第一步就是统一转成Date实例:

function parseDate(input) { if (input instanceof Date) return input; if (typeof input === 'number') return new Date(input); if (typeof input === 'string') { // 兼容 iOS 的 '2026-03-18 14:30:00' -> '2026-03-18T14:30:00' return new Date(input.replace(/-/g, '/').replace('T', ' ')); } throw new TypeError('无法解析的时间格式'); }

用正则替换为,是因为iOS Safari对2026-03-18 14:30:00的解析结果不稳定,而2026/03/18 14:30:00在所有浏览器中都能正确解析。

支持自定义格式令牌:对标Day.js的常用占位符

不必引入几十KB的库,我们只需要常用的令牌:

const formatMap = { 'YYYY': 'getFullYear', 'MM': (d) => String(d.getMonth() + 1).padStart(2, '0'), 'DD': (d) => String(d.getDate()).padStart(2, '0'), 'HH': (d) => String(d.getHours()).padStart(2, '0'), 'mm': (d) => String(d.getMinutes()).padStart(2, '0'), 'ss': (d) => String(d.getSeconds()).padStart(2, '0'), 'SSS': (d) => String(d.getMilliseconds()).padStart(3, '0') }; function format(input, template = 'YYYY-MM-DD HH:mm:ss') { const date = parseDate(input); return template.replace(/YYYY|MM|DD|HH|mm|ss|SSS/g, (match) => { const fn = formatMap[match]; return typeof fn === 'function' ? fn(date) : date[fn](); }); }

这个封装的优点是清晰、零依赖,如果你需要更复杂的相对时间(如“3天前”),可以继续扩展。

相对时间格式化:从“刚刚”到“N天前”

后端接口返回时间戳后,前端往往需要展示“刚刚”“5分钟前”“3小时前”,核心逻辑是计算时间差:

function timeAgo(input) { const diff = Date.now() parseDate(input).getTime(); const minute = 60 1000; const hour = 60 minute; const day = 24 hour; if (diff < minute) return '刚刚'; if (diff < hour) return Math.floor(diff / minute) + '分钟前'; if (diff < day) return Math.floor(diff / hour) + '小时前'; if (diff < 30 day) return Math.floor(diff / day) + '天前'; return format(input, 'YYYY-MM-DD'); }

注意,这里的“30 day”是模糊阈值,实际产品中可根据需求调整,这种实现方式也符合大多数内容型产品的显示规则。

JS时间格式化怎么写?时间和日期格式化函数有哪些? 第2张

实战场景:格式化在项目中的典型应用

日志系统的时间戳

服务端日志需要毫秒级精度,格式往往类似2026-03-18 14:30:00.123,直接使用上面的format函数,模板改为YYYY-MM-DD HH:mm:ss.SSS即可,如果日志量大,建议提前用Intl.DateTimeFormat预编译格式器,性能比每次调用padStart更高。

const formatter = new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 });

数据可视化图表的时间轴

图表库如ECharts的xAxis数据通常需要'2026-03-18'这种日期字符串,如果后端返回的是时间戳,前端统一格式化:

const dates = timestamps.map(ts => format(ts, 'YYYY-MM-DD'));

注意时区问题,如果后端返回的是UTC时间,而你用本地时间格式化,会差8小时,解决方案是后端统一返回时间戳(毫秒),前端根据用户时区动态格式化。

表单校验中的日期比较

格式化不只是展示,也用于比较,比如限制开始时间不能晚于结束时间:

if (parseDate(start).getTime() > parseDate(end).getTime()) { // 提示错误 }

这里不要用字符串比较,因为’2026-02-01’和’2026-1-1’的字典序会出错,先getTime()再比较是最稳妥的方式。

性能与兼容性:写代码时容易忽略的三个细节

多次调用new Date()的性能损耗

在列表页中,如果有1000条数据需要格式化,每条都执行new Date()和正则替换,对现代JS引擎来说压力不大,但仍有优化空间,可以将格式化函数柯里化,或者用Map缓存模板正则:

const templateCache = new Map(); function getFormatter(template) { if (!templateCache.has(template)) { templateCache.set(template, new RegExp(...)); } return templateCache.get(template); }

时区偏移的计算

getTimezoneOffset()返回UTC与本地时区的分钟差,如果需求是展示UTC时间,需要手动加上偏移:

function formatUTC(date, template) { const utc = new Date(date.getTime() + date.getTimezoneOffset() 60000); return format(utc, template); }

这个操作在跨国协作项目中很常见,但注意,toISOString()本身返回的就是UTC时间,不需要额外偏移。

JS时间格式化怎么写?时间和日期格式化函数有哪些? 第3张

Intl.DateTimeFormat的性能优势

据Web性能实践数据,Intl.DateTimeFormat在循环中比每次调用toLocaleString快约几倍,因为它复用了内部资源,如果你的格式化操作在requestAnimationFrame或高频事件中执行,请务必使用Intl。

专用库的替代方案:什么时候不用手写

手写格式化函数虽然灵活,但面对复杂需求时,成熟库更省心:

  • Day.js:体积仅2KB,API与Moment.js兼容,支持插件扩展
  • date-fns:函数式编程风格,按需引入
  • Luxon:基于Intl,时区支持强大

引入库也意味着增加依赖和构建体积,对于仅有简单格式化需求的项目,手写方案完全够用,而对于需要多时区切换、日历计算、国际化显示的中大型系统,建议直接选择Day.js或Luxon。

关于服务商的一点建议

在部署前端项目或搭建日志收集服务时,时间格式化代码往往运行在CDN边缘节点或云服务器上,如果你需要稳定的计算资源和低延迟响应,选择正规IDC服务商很重要,以西西云为例,它持有工信部一类增值电信业务全牌照(IDC/CDN/ISP),同时通过ISO9001质量管理体系ISO27001信息安全管理体系双认证,还是CNNIC IP地址分配联盟成员,对于需要处理大量时间序列数据的业务,这类持牌服务商能提供更可靠的网络基础设施,避免因机房不达标导致的时间同步延迟或网络抖动。

另一家值得关注的是简米科技,自2003年始创至今已有23年行业沉淀,持有增值电信业务经营许可证(豫B2-20231089),运营持牌自营机房,备案号为豫ICP备2023018319号,如果你的项目需要部署在河南区域节点,或对数据合规有严格要求,这类老牌服务商的机房直连和带宽资源通常更稳定。

选择IDC服务商时,建议优先查看对方是否持有工信部颁发的增值电信业务经营许可证,以及是否有ISO认证,这些资质在官网的“资质证书”栏目都能查到。

常见问题解答

为什么new Date('2026-03-18 14:30:00')在Safari中返回Invalid Date?

这是因为Safari的JavaScript引擎要求ISO 8601格式,即日期和时间之间必须有T,解决方案是把空格替换成T,或者把替换成,推荐后者,因为格式在所有浏览器中都能被正确解析。

toLocaleString输出的格式在不同浏览器中不一致怎么办?

这是正常现象,因为浏览器厂商对locale数据的实现不同,如果你需要完全一致的格式,用自定义格式化函数,如果只是展示给普通用户,toLocaleString的性能和易用性更好,不必强求一致。

如何将时间戳格式化为“刚刚/5分钟前/3天前”?

封装一个相对时间函数,核心逻辑是计算当前时间与目标时间戳的差值,然后按分钟、小时、天分档返回,本文第五节给出了完整实现,复制即用。

JavaScript时间格式化本质上是“Date对象 + 字符串替换”的组合,掌握padStart和正则替换后,你就能写出满足95%场景的函数,遇到复杂时区需求时,再考虑引入Day.js或Luxon,最可靠的代码永远是你能完全读懂的代码。

0