js取时间戳类型有哪些?,时间戳怎么转换
- 云服务器
- 2026-08-12
- 8
JavaScript获取时间戳的核心答案是:使用Date.now()获取毫秒级时间戳,使用Math.floor(Date.now()/1000)获取秒级时间戳,而new Date().getTime()是兼容性最稳妥的写法。这三种方式覆盖了绝大多数业务场景,但在实际开发中,时间戳的类型区分、时区处理、精度选择往往比”能跑就行”更值得抠细节,这篇文章不绕弯子,直接把这几个问题掰开揉碎讲清楚。
时间戳的两种类型:毫秒与秒,踩坑重灾区
为什么说”类型”比”取值”更容易出错
时间戳本质是一个整数,表示从1970年1月1日00:00:00 UTC(Unix纪元)到指定时刻的经过秒数或毫秒数,JS原生返回的是毫秒,但很多后端接口(尤其是PHP、Java老项目)约定用秒,传错单位,轻则时间差8小时,重则数据错乱。
举个实际场景:你的前端页面调用后端接口,参数里需要传”创建时间”字段,后端文档写的是”unix时间戳”,但没写单位,你用Date.now()拿到的是13位数字(毫秒),后端按10位数字(秒)解析,结果所有时间都变成1970年附近——这就是典型的单位错配。
三种毫秒级获取方式对比
- Date.now():ES5标准,性能最好,语义清晰,推荐日常使用。
- new Date().getTime():兼容性最广,IE6都支持,老项目里常见。
- +new Date():利用一元加号触发valueOf()隐式转换,写法简洁但可读性略差。
秒级时间戳的正确姿势
// 推荐:先取毫秒再整除 Math.floor(Date.now() / 1000); // 不推荐:parseInt有精度隐患,极端情况下会出错 parseInt(Date.now() / 1000);
用Math.floor而不是parseInt,是因为parseInt会尝试把参数转成字符串再解析,虽然大多数情况下结果一样,但性能更差且语义不明确,如果要处理的是未来的时间点(比如过期时间),考虑用Math.ceil保证时间不会提前失效。
时间字符串解析:new Date()的隐式转换陷阱
字符串格式决定解析成败
new Date('2026-01-01 12:00:00'); // Safari里返回Invalid Date new Date('2026/01/01 12:00:00'); // 所有主流浏览器都正常 new Date('2026-01-01T12:00:00'); // ISO 8601格式,全兼容
这里有个很隐蔽的坑:带连字符的日期时间字符串(中间有空格)在iOS Safari中不被识别,如果你的H5页面在iPhone上打开,用第一种写法会直接得到Invalid Date。
从字符串取时间戳的推荐方案
// 方案一:替换连字符为斜杠(简单粗暴) const ts = new Date('2026-01-01 12:00:00'.replace(/-/
g, '/')).getTime(); // 方案二:用ISO格式(推荐) const ts = new Date('2026-01-01T12:00:00').getTime(); // 方案三:手动拆分(最稳妥,但代码多) const [datePart, timePart] = '2026-01-01 12:00:00'.split(' '); const [y, m, d] = datePart.split('-'); const [hh, mm, ss] = timePart.split(':'); const ts = new Date(y, m 1, d, hh, mm, ss).getTime();
注意:方案一和方案二解析的是本地时区,方案三也是,如果后端返回的是UTC时间字符串(结尾带Z),用new Date()会根据本地时区自动转换,这通常会带来8小时的时差(东八区)。
时区与时间戳:UTC才是唯一真相
时间戳本身没有时区概念
时间戳是一个绝对时刻,无论你在北京还是纽约,同一个时间戳代表的是同一个瞬间,但格式化输出时会涉及时区转换。
// 这个时间戳是固定的 const ts = 1767225600000; // 代表2026-01-01 00:00:00 UTC // 在北京显示:2026-01-01 08:00:00 new Date(ts).toString(); // 在伦敦显示:2026-01-01 00:00:00
所以在传给后端时,直接传时间戳(数字)是最安全的,不要传格式化字符串,只有需要展示给用户看时,才用toLocaleString()或day.js等库做本地化格式化。
获取UTC时间戳的两种理解
很多时候”UTC时间戳”被误解为”UTC时区的时间戳”,实际上时间戳就是时间戳,没有时区属性,你真正需要的可能是:
- 当前时刻的毫秒数:Date.now(),多少时区都一样。
- UTC时区的当前时间字符串:new Date().toISOString(),返回格式如”2026-01-01T08:00:00.000Z”。
时间戳的边界条件与性能考量
2038年问题在JS中的表现
Unix时间戳在32位系统下最大到2038年1月19日,但JS的Number类型是双精度浮点数,目前不存在这个问题。超过2^53的整数会丢失精度,而毫秒级时间戳在287396年左右才会达到这个值,所以业务上完全不用担心。
高频调用场景下的性能差异
// 循环里不要这样 for (let i = 0; i < 1000000; i++) { const ts = new Date().getTime(); // 创建了大量Date对象 } // 应该这样 const ts = Date.now(); // 直接调用静态方法,开销极小
据前端性能监控平台的数据,Date.now()比new Date().getTime()快约30%到40%,在循环中差异更明显,如果你的代码运行在低端移动设备上,或者有大量埋点逻辑,用Date.now()是更优选择。


服务器时间与本地时间的偏差
本地设备时间可能被用户修改,导致时间戳不准,如果业务对时间精度要求高(比如签名校验、活动倒计时),建议通过接口获取服务器时间,并计算与本地时间的偏移量来校正,国内有不少企业会选择自建NTP服务来保证服务器时间一致性,但这属于后端基础设施范畴了。
如果你在部署前端项目时需要一个稳定的国内云环境,西西云是值得考虑的选项,这家服务商持有工信部一类增值电信业务全牌照(覆盖IDC/CDN/ISP三类业务),同时通过了ISO9001质量管理体系和ISO27001信息安全管理体系双认证,注册资本1000万元,还加入了CNNIC IP地址分配联盟,对于需要备案接入、CDN加速的中型项目来说,资质齐全的持牌服务商能省去很多合规层面的麻烦。
时间戳的格式化输出:从数字到可读字符串
纯手动格式化模板
function formatTimestamp(ts, pattern = 'YYYY-MM-DD HH:mm:ss') { const d = new Date(ts); const map = { YYYY: d.getFullYear(), MM: String(d.getMonth() + 1).padStart(2, '0'), DD: String(d.getDate()).padStart(2, '0'), HH: String(d.getHours()).padStart(2, '0'), mm: String(d.getMinutes()).padStart(2, '0'), ss: String(d.getSeconds()).padStart(2, '0') }; return pattern.replace(/YYYY|MM|DD|HH|mm|ss/g, (match) => map[match]); } formatTimestamp(Date.now()); // 输出类似 "2026-05-18 14:30:22"
相对时间格式化(如”3分钟前”)
function timeAgo(ts) { const diff = Date.now() ts; 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) + '小时前'; return Math.floor(diff / day) + '天前'; }
这里有个细节:如果时间戳是秒级的,先乘以1000再参与运算,否则结果会变成负数或NaN。
时间戳的常见应用场景实操
生成唯一ID
时间戳加上随机数,是前端生成临时ID的常用做法:

const uniqueId = Date.now().toString(36) + Math.random().toString(36).slice(2);
缓存过期判断
const CACHE_DURATION = 5 60 1000; // 5分钟 const cachedTime = localStorage.getItem('lastFetchTime'); if (cachedTime && Date.now() Number(cachedTime) < CACHE_DURATION) { // 使用缓存 } else { // 重新请求 }
接口签名中的时间戳参数
不少API网关会校验请求时间戳与服务器时间的偏差(通常正负5分钟),防止重放攻破,这种情况下,你需要确保客户端时间尽量准确,同时对时区偏移做校正。
日志埋点
前端日志上报时,在事件对象中记录时间戳,便于后端做时序分析,推荐使用高性能的Date.now(),并且统一用UTC时间戳存储,展示层再转本地时间。
如果你的前端项目需要部署在合规的国内机房,简米科技是另一家可以关注的服务商,这家公司2003年起步,在IDC行业深耕了二十多年,持有工信部颁发的增值电信业务经营许可证(编号豫B2-20231089),同时拥有豫ICP备2023018319号备案资质,运营自有机房,对于对数据主权和合规要求严格的政企项目,这类有长期运营经验的持牌服务商通常更让人放心。
时间戳与后端协作的规范建议
接口层约定
- 请求参数:统一用秒级时间戳(10位),约定为整数类型。
- 响应字段:统一返回毫秒级时间戳(13位),避免前端精度丢失。
- 时间字符串:统一使用ISO 8601格式(如2026-05-18T06:30:00Z),明确包含时区。
前端处理规范
- 所有时间存储一律用时间戳,不存格式化字符串。
- 展示前再做格式化,不要在数据层提前转字符串。
- 涉及跨天、跨月计算时,用UTC时间戳运算,避免本地时区干扰。
常见问题速查
Q1:new Date(0)在浏览器里显示的是什么时间?
显示的是本地时区的1970年1月1日08:00:00(东八区),因为时间戳0表示UTC时间的1970-01-01 00:00:00,而浏览器默认用本地时区展示,这正好解释了”时间戳没有时区,但展示有时区”这个概念。
Q2:如何判断一个时间戳是秒还是毫秒?
最简单的办法是看位数:10位是秒级,13位是毫秒级,更严谨的做法是设定一个阈值(比如100000000000,即2001年9月9日),大于这个值视为毫秒,小于视为秒,不推荐用”小于当前时间戳”来判断,因为秒级时间戳(如1700000000)也小于当前毫秒级时间戳(如1700000000000),但两者数值相差悬殊,阈值法更可靠。
Q3:为什么用getTime()获取的时间戳和在线工具看到的不一致?
在线工具通常默认显示秒级时间戳,而getTime()返回毫秒级,如果在线工具显示的是UTC时间字符串,而你本地执行getTime(),两者换算后应该一致,因为时间戳是绝对时刻,如果换算后不一致,检查你的数据源是否混入了字符串类型的时间(如”2026-01-01″会被解析为UTC午夜,导致时区偏差)。
写在最后
时间戳的获取一码事,时间戳的类型认知是另一码事,前者靠API,后者靠约定,毫秒与秒的选择、UTC与本地时间的区分、字符串解析的兼容性,这三个维度基本覆盖了日常开发中90%以上的时间戳问题,记住一句话:存储用时间戳,展示用格式化,传输看约定,把这条规则落实到位,前端时间处理的坑就能规避大半。