【问题标题】:How to change process date on NodeJS instead of change system date directly?如何更改 NodeJS 上的处理日期而不是直接更改系统日期?
【发布时间】:2018-04-17 15:15:10
【问题描述】:

我想做一些在使用 Date 类时需要更改进程日期的测试:

console.log(Date.now())

正常运行我的程序,进程将获取机器当前时间:

"scripts": {
   "start": "node testDate.js"
}

是否有类似 cross-env 的东西来更改初始处理日期?

"scripts": {
   "start": "cross-env CURRENT_DATE=<future-date> node testDate.js"
}

或者在运行时有解决方案吗?

NodeJS 可以更改进程日期吗?

process.DATE_CLOCK=Date("<future-date>")

console.log(Date.now())// will print the future date + time passed after  previous line has been executed

【问题讨论】:

  • 可以在node.js调用后向node脚本发送参数。例如:$node testDate.js 1520978956795 在 Node 中,您需要将此时间戳字符串作为数字解析给 Date 构造函数:var _date = new Date(parseFloat(process.argv[2])); 并且新的 Date 对象将带有您作为参数发送的时间戳。对于未来的日期,您可以发送可以添加到 Date.now() 的时间戳偏移量
  • 是的,我知道!但我想要一个全局解决方案来模拟具有未来值或任何其他值的日期!而且代码的每一部分都不会改变!
  • 您找到解决方案了吗?
  • 在文件顶部可以添加if(process.env.testFlag==true))Date.now = () =&gt; { return new Date().getTime() - 60 * 60 * 1000; };

标签: javascript node.js date process environment-variables


【解决方案1】:

我认为这不可能通过现有的节点环境变量实现,但您应该 查看mockdate 包。

这是一个在单元测试中使用的示例。

// mut.js
module.exports = {
    getCurrentDate: () => Date.now()
}


// mut.test.js
const mut = require('./mut');
const mockdate = require('mockdate');

describe('mut', () => {
    const mockedTime = 1609865118363;

    it('should return adjusted date', () => {
        mockdate.set(mockedTime);
        expect(mut.getCurrentDate())
            .toEqual(mockedTime);
    });

    it('should return current date/time', () => {
        mockdate.reset();
        expect(mut.getCurrentDate())
            .not.toEqual(mockedTime);
    });
});

如果您坚持通过节点环境添加它,您可以添加类似于 Sengupta Amit 注释的进程环境检查并包装您的应用程序入口点。这会将时间设置为类似于您上面要求的时间。

//testDate.js
// CURRENT_DATE=1609865118363 node ./testDate.js

const mockdate = require('mockdate');
const mut = require('./mut');
const currentDate = process.env.CURRENT_DATE;
if (currentDate) mockdate.set(parseInt(currentDate));

console.log(mut.getCurrentDate()); // will log 1609865118363 to console

编辑: 还使用 Express 和 Node Http Server 对此进行了测试。它仍然有效,并将返回 Date 标头,并通过 mockdate 设置时间。

// CURRENT_DATE=1609865118363 node testDate.js
const app = require('express')();
const mockdate = require('mockdate');
const currentDate = process.env.CURRENT_DATE;
if (currentDate) mockdate.set(parseInt(currentDate));

app.get('/', (req, res) => res.send());

app.listen(3000, (err) => {
    if(err) console.log(err);
})

const mockdate = require('mockdate');
const currentDate = process.env.CURRENT_DATE;
if (currentDate) mockdate.set(parseInt(currentDate));

const http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200);
  res.end();
}).listen(8080);

【讨论】:

  • 这不适用于 Node.js 内部设置的日期,例如 http 服务器设置的日期标头,因为这些日期由节点内部维护,而不是用户外部维护。 (mockdate 是 @sinon/fake-timers 的一个不太流行的版本,也被 jest 使用,我帮助维护它采用了类似的方法)
  • 已经测试过 Express 和普通的普通 http 服务器,它会覆盖响应头中的时间。我可能没有正确解释您评论的上下文,您是正确的,在某些情况下这可能不起作用。
  • 尝试现代节点(> 15.2.0),我添加了赏金,看看是否有人可以解决github.com/sinonjs/fake-timers/issues/344
猜你喜欢
  • 1970-01-01
  • 2011-07-22
  • 1970-01-01
  • 2022-08-17
  • 2010-10-12
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多