Javascript 如何在javascript中伪造时间?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7931069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:06:20  来源:igfitidea点击:

How to fake time in javascript?

javascript

提问by Leo Zhang

I would like to mock the Date constructor so that whenever I call new Date(), it always return specific time.

我想模拟 Date 构造函数,以便每当我调用 new Date() 时,它总是返回特定时间。

I found Sinon.js provide useFakeTimers to mock time. But the following code doesn't work for me.

我发现 Sinon.js 提供 useFakeTimers 来模拟时间。但以下代码对我不起作用。

sinon.useFakeTimers(new Date(2011,9,1));

//expect : 'Sat Oct 01 2011 00:00:00' ,

//result : 'Thu Oct 27 2011 10:59:44‘
var d = new Date();

回答by tothemario

sinon.useFakeTimersaccepts a timestamp (integer) as parameter, not a Date object.

sinon.useFakeTimers接受时间戳(整数)作为参数,而不是 Date 对象。

Try with

试试

clock = sinon.useFakeTimers(new Date(2011,9,1).getTime());
new Date(); //=> return the fake Date 'Sat Oct 01 2011 00:00:00'

clock.restore();
new Date(); //=> will return the real time again (now)

If you use anything like setTimeout, make sure you read the docs because the useFakeTimerswill disrupt the expected behavior of that code.

如果您使用类似setTimeout,请确保您阅读文档,因为这useFakeTimers会破坏该代码的预期行为。

回答by Mike Christensen

How about something like this?

这样的事情怎么样?

var oldDate = Date;
Date = function (fake)
{
   return new oldDate('03/08/1980');
}

var x = new Date();
document.write(x);

You'd then, of course, run:

你当然会运行:

Date = oldDate;

Date = oldDate;

When you wanted to restore things to normal behavior.

当您想将事情恢复到正常行为时。

回答by Gilles Castel

You can also use Proxies:

您还可以使用代理

window.Date = new Proxy(Date, {
    construct: function(target, args) {
        if (args.length === 0) {
            return new target(2017, 04, 13, 15, 03, 0);
        }
        return new target(...args);
    }
});

回答by Bjorkegeek

This is what I needed for my project. A bit complex, but as far as I can tell it's all needed. The internal Date() is a strange beast. Also the code below uses underscorejs.

这是我的项目所需要的。有点复杂,但据我所知,这一切都需要。内部 Date() 是一个奇怪的野兽。下面的代码也使用 underscorejs。

(window || global).Date = (function (orgDate) {
    var fakeDate = function (y, m, d, ho, mi, se, mil) {
        var backendDate;
        if (arguments.length > 3) {
            backendDate = new orgDate(y, m, d, ho || 0, mi || 0, se || 0, mil || 0);
        } else if (arguments.length > 1) {
            backendDate = new orgDate(y, m || 0, d || 0);
        } else if (arguments.length > 0) {
            backendDate = new orgDate(y);
        } else {
            backendDate = new orgDate();
            backendDate.setFullYear(2015);  // <-- Your year here
            backendDate.setMonth(1);        // <-- Your month here
            backendDate.setDate(2);         // <-- Your day here
        }
        if (this) {
            this.backendDate = backendDate;
        }
        return backendDate.toString();
    }
    _.each(("getDate getDay getFullYear getHours getMilliseconds getMinutes " +
            "getMonth getSeconds getTime getTimezoneOffset getUTCDate getUTCDay " +
            "getUTCFullYear getUTCHours getUTCMilliseconds getUTCMinutes " +
            "getUTCMonth getUTCSeconds getYear parse setDate setFullYear setHours " +
            "setMilliseconds setMinutes setMonth setSeconds setTime setUTCDate " +
            "setUTCFullYear setUTCHours setUTCMilliseconds setUTCMinutes " +
            "setUTCMonth setUTCSeconds setYear toDateString toGMTString " +
            "toISOString toJSON toLocaleDateString toLocaleTimeString " +
            "toLocaleString toString toTimeString toUTCString UTC valueOf").split(" "),
        function (fnName) {
            fakeDate.prototype[fnName] = function () {
                return this.backendDate[fnName].apply(this.backendDate, arguments);
            }
        });
    return fakeDate;
})(window.Date);

回答by Jan Prichystal

I ended up doing:

我最终做了:

var oldDate = Date;
Date = function (fake)
{
    if( ! fake ) return new oldDate('02/26/2017');

    return new oldDate(fake);
}
Date.prototype = oldDate.prototype;

回答by Anatoli Klamer

sinon.useFakeTimers is using lolex internally. So it supports object as parameter for lolex

sinon.useFakeTimers 在内部使用 lolex。所以它支持对象作为lolex的参数

sinon.useFakeTimers(new Date(2019,1,1)) 

is equivalent for

等价于

sinon.useFakeTimers({
now:new Date(2019,1,1)
}) 

My task was to use same begin date on every integration test (as date should be connected with data in files) So how i'm using it

我的任务是在每个集成测试中使用相同的开始日期(因为日期应该与文件中的数据相关联) 那么我是如何使用它的

 clock = sinon.useFakeTimers({
  now,
  shouldAdvanceTime: true,
  advanceTimeDelta: 20
});

shouldAdvanceTimewill allows lolex and sinon to not stop timers in my integration tests. Also take a look on config.toFakeparameter. It allows to avoid mocking some functions like setTimeout. Or just mock only Dateconstructor

shouldAdvanceTime将允许 lolex 和 sinon 在我的集成测试中不停止计时器。还要看一下config.toFake参数。它允许避免模拟某些函数,例如setTimeout. 或者只是模拟Date构造函数