Day.js和Moment.js中获取时间戳的API用法

作者:函数茶馆时间:2026-11-03 09:01:24浏览:266

详细讲解在Day.js和Moment.js中获取13位毫秒级与10位秒级时间戳的核心API用法,对比valueOf、unix、隐式转换等方法的使用场景、反向解析机制与避坑要点。

在 JavaScript 日期时间处理中,获取时间戳是最基础且高频的操作。无论是轻量级的 Day.js 还是经典的 Moment.js,都提供了统一的 API 规范:获取 13位毫秒级时间戳 使用 .valueOf(),获取 10位秒级时间戳 使用 .unix()。本文详细梳理两者的核心 API 调用方式、类型特征、反向解析方法及高频陷阱,帮助开发者规范、准确地处理时间戳数据。
Day.js和Moment.js中获取时间戳的API用法
图 0:Day.js 与 Moment.js 获取时间戳 API 核心映射

一、时间戳精度区分:13位毫秒与10位秒

在讨论 API 之前,必须先明确 JavaScript 生态中两类常见的时间戳概念:

  • 13 位毫秒级时间戳(Milliseconds):指从 Unix 纪元(1970年1月1日 00:00:00 UTC)起至当前时刻经过的毫秒数,例如 1700000000000。原生 JavaScript 中的 Date.now() 和 new Date().getTime() 默认返回的正是此精度。
  • 10 位秒级时间戳(Seconds / Unix Timestamp):指自 Unix 纪元起经过的整秒数,例如 1700000000。在后端接口设计、Linux 系统接口以及各类开放协议(如 OAuth)中更为普遍。

Day.js 在设计上最大程度保持了对 Moment.js API 的兼容,因此在这两类时间戳的获取上,两个库的函数名称与行为几乎完全一致。

二、获取毫秒级时间戳(13位)的具体 API 与用法

获取 13 位毫秒级时间戳通常有以下几种方式,推荐首选语义清晰的 .valueOf() 方法。

1. 使用 .valueOf() 方法

.valueOf() 会返回以毫秒为单位的数字(number 类型),表示 Unix 纪元至今的微秒/毫秒偏移。

// Day.js 示例
const dayjs = require('dayjs');
const msDay = dayjs().valueOf();
console.log(msDay);        // 示例输出: 1714521600000
console.log(typeof msDay); // 示例输出: "number"

// Moment.js 示例
const moment = require('moment');
const msMoment = moment().valueOf();
console.log(msMoment);     // 示例输出: 1714521600000
console.log(typeof msMoment); // 示例输出: "number"

2. 使用一元加号操作符(+ 隐式类型转换)

在 JavaScript 中,当对一个对象使用一元加号 + 时,JS 引擎会内部调用对象的 valueOf() 方法,将其强制转换为原始数值类型。因此 +dayjs() 和 +moment() 是简洁的等效写法:

const timestamp1 = +dayjs();   // 1714521600000
const timestamp2 = +moment();  // 1714521600000

3. 转为原生 Date 对象后获取(.toDate().getTime())

如果需要配合只接受原生 Date 的遗留库,可通过 .toDate() 取出原生 Date 实例,再调用其原生的 .getTime():

const jsDateMs = dayjs().toDate().getTime(); // 1714521600000
Day.js和Moment.js中获取时间戳的API用法
图 1:时间戳获取的执行步骤与精度决策流程

三、获取秒级时间戳(10位)的具体 API 与用法

在后端服务交互、数据签名、Token 过期时间计算等场景中,经常需要 10 位的 Unix 秒级时间戳。Day.js 和 Moment.js 提供了极其简洁的方法:

1. 使用 .unix() 方法

调用 .unix() 可以直接得到自 1970-01-01 00:00:00 UTC 算起的秒数。它返回的是一个经过向下取整的整数(number 类型)。

// Day.js
const dayjs = require('dayjs');
const secDay = dayjs().unix();
console.log(secDay);        // 示例输出: 1714521600
console.log(typeof secDay); // 示例输出: "number"

// Moment.js
const moment = require('moment');
const secMoment = moment().unix();
console.log(secMoment);     // 示例输出: 1714521600
console.log(typeof secMoment); // 示例输出: "number"

2. 手动取整转换(底层计算逻辑)

两个库内部对于 .unix() 的实现逻辑实际上都等价于:

const manualSec = Math.floor(instance.valueOf() / 1000);

了解这一原理可以帮助我们理解:在秒级转换时,当前秒内的毫秒部分会被舍弃(向下取整截断),因此从秒级时间戳反转回毫秒时,末尾三位总是 000。

四、Day.js 与 Moment.js 的差异与底层机制分析

虽然两者的 API 名称一致,但在底层对象机制上存在重大差异:不可变性(Immutability)。

  • Moment.js 的可变对象陷阱:在 Moment.js 中,调用 .add()、.subtract() 等方法会直接修改原有对象本身。如果在一个实例上连续链式运算并获取时间戳,原对象已经被改变。
  • Day.js 的不可变性:Day.js 借鉴了现代函数式编程理念,所有的日期修改操作均返回一个新的 Dayjs 实例,原有对象永远保持只读。
// Moment.js 可变性测试
const m1 = moment('2024-05-01');
const m2 = m1.add(1, 'day');
console.log(m1.valueOf() === m2.valueOf()); // true!m1 被连带修改了

// Day.js 不可变性测试
const d1 = dayjs('2024-05-01');
const d2 = d1.add(1, 'day');
console.log(d1.valueOf() === d2.valueOf()); // false!d1 保持不变
Day.js和Moment.js中获取时间戳的API用法
图 2:Day.js 与 Moment.js 架构机制与适用场景对比

五、时间戳反向解析(Timestamp to Date/Object)

在实际开发中,获取时间戳的下一环通常是解析接收到的时间戳。针对 13 位毫秒和 10 位秒,解析入口必须严格对应:

1. 解析 13 位毫秒级时间戳

对于毫秒级时间戳,直接传入主函数构造器即可:

const msValue = 1714521600000;

// Day.js
const dateFromDay = dayjs(msValue);
console.log(dateFromDay.format('YYYY-MM-DD HH:mm:ss'));

// Moment.js
const dateFromMoment = moment(msValue);
console.log(dateFromMoment.format('YYYY-MM-DD HH:mm:ss'));

2. 解析 10 位秒级时间戳

若将 10 位秒级时间戳误当作毫秒直接传入 dayjs(1714521600),会被解析为 1970 年 1 月的最初几十天(因为被当成了 171 万毫秒)。解析 10 位时间戳必须使用 .unix() 静态方法:

const secValue = 1714521600;

// 正确做法:使用静态工厂方法 .unix()
const d = dayjs.unix(secValue);   // Day.js 正确解析
const m = moment.unix(secValue);  // Moment.js 正确解析

// 或者手动乘以 1000 转为毫秒:
const dManual = dayjs(secValue * 1000);
Day.js和Moment.js中获取时间戳的API用法
图 3:时间戳提取与反向解析还原的全链路对应关系

六、实际开发中容易混淆的常见陷阱与注意事项

1. 时区与时间戳的独立性

核心认知:Unix 时间戳代表的是物理世界中自 1970-01-01 00:00:00 UTC 起流逝的绝对时长,与本地时区无关。

无论当前电脑处于东八区(UTC+8)还是格林威治(UTC+0),同一时刻调用 dayjs().valueOf() 得到的数值必然相同。许多初学者常误以为切换到 UTC 模式后时间戳会相差 8 个小时,实际调用 dayjs().utc().valueOf() 与 dayjs().valueOf() 的结果完全相等。时区只影响时间戳格式化为文本(如 YYYY-MM-DD HH:mm:ss)时的展示。

2. 使用 .format('X') 与 .format('x') 获取的是字符串而不是数值

除了 .valueOf() 和 .unix() 之外,格式化方法也支持时间戳占位符:

  • instance.format('x'):返回 13 位毫秒级时间戳字符串。
  • instance.format('X'):返回 10 位秒级时间戳字符串。
注意区别:.valueOf() 和 .unix() 的返回值是纯数字(number),而 .format() 的返回值永远是字符串(string)。在需要进行数值比大小或传输给只接受数值的后端接口时,切忌直接混用。

3. 避免将 10 位秒级时间戳直接传给 dayjs()

如前文所述,在接收服务端返回的时间戳时,务必先确认长度是 10 位还是 13 位:

// 健壮的动态解析函数示例
function parseTimestamp(ts) {
  const num = Number(ts);
  // 10位秒级(小于 1000 亿)按 unix 解析,否则按毫秒解析
  return num < 100000000000 ? dayjs.unix(num) : dayjs(num);
}

七、API 选型与速查总结

为了在实际编码时快速查阅,以下总结了 Day.js 与 Moment.js 获取时间戳及相关操作的速查表:

目标任务 Day.js API Moment.js API 返回值类型 典型输出示例
获取 13 位毫秒时间戳 dayjs().valueOf() 或 +dayjs() moment().valueOf() 或 +moment() number 1714521600000
获取 10 位秒级时间戳 dayjs().unix() moment().unix() number 1714521600
获取毫秒字符串 dayjs().format('x') moment().format('x') string "1714521600000"
获取秒级字符串 dayjs().format('X') moment().format('X') string "1714521600"
从 13 位毫秒反向解析 dayjs(ms) moment(ms) Dayjs / Moment 实例 包装对象
从 10 位秒级反向解析 dayjs.unix(sec) moment.unix(sec) Dayjs / Moment 实例 包装对象
Day.js和Moment.js中获取时间戳的API用法
图 4:时间戳获取 API 选型与场景避坑总结决策图
作者最新文章
相关文章
更多