如何模拟 javascipt new Date 以从浏览器控制台返回不同的日期

问题描述 投票:0回答:4

我使用的一个网站在不同日期显示不同的内容。在 JavaScript 中,它使用

new Date()
来确定当前日期,并使用当前日期来确定要显示的内容。

如果我想查看不同日期的内容,我可以更改系统时间。然而,这很乏味并且会干扰其他应用程序。我想弄清楚是否有一些代码可以在浏览器的 javascipt 控制台中运行,该代码将模拟

new Date()
返回我选择的日期

我看到有一些问题讨论用玩笑在 Date 上创建间谍,但我没有看到在我的浏览器控制台中模拟这个的方法

javascript date jestjs mocking
4个回答
4
投票

可以用您自己的函数替换

Date
函数来提供您想要的结果,但是在页面使用它之前执行此操作会很棘手,除非您编写浏览器扩展。

基本的一点是(见评论):

// Save the original `Date` function
const OriginalDate = Date;
// Replace it with our own
Date = function Date(...args) {
    // Called via `new`?
    if (!new.target) {
        // No, just pass the call on
        return OriginalDate(...args);
    }
    // Determine what constructor to call
    const ctor = new.target === Date ? OriginalDate : new.target;
    // Called via `new`
    if (args.length !== 0) {
        // Date constructor arguments were provided, just pass through
        return Reflect.construct(ctor, args);
    }
    // It's a `new Date()` call, mock the date we want; in this
    // example, Jan 1st 2000:
    return Reflect.construct(ctor, [2000, 0, 1]);
};
// Make our replacement look like the original (which has `length = 7`)
// You can't assign to `length`, but you can redefine it
Object.defineProperty(Date, "length", {
    value: OriginalDate.length,
    configurable: true
});

// Save the original `Date` function
const OriginalDate = Date;
// Replace it with our own
Date = function Date(...args) {
    // Called via `new`?
    if (!new.target) {
        // No, just pass the call on
        return OriginalDate(...args);
    }
    // Determine what constructor to call
    const ctor = new.target === Date ? OriginalDate : new.target;
    // Called via `new`
    if (args.length !== 0) {
        // Date constructor arguments were provided, just pass through
        return Reflect.construct(ctor, args);
    }
    // It's a `new Date()` call, mock the date we want; in this
    // example, Jan 1st 2000:
};
// Make our replacement look like the original (which has `length = 7`)
// You can't assign to `length`, but you can redefine it
Object.defineProperty(Date, "length", {
    value: OriginalDate.length,
    configurable: true
});

console.log("new Date()", new Date());
console.log("new Date(2021, 7, 3)", new Date(2021, 7, 3));


1
投票

谢谢 @t-j-crowder 🙏 迄今为止我找到的最好的解决方案...我对其进行了一些自定义,因此 Date.now 也可以工作。

还有一个建议,在脚本的最开始放置断点,在控制台中运行代码并恢复执行以获得最佳的日期一致性😌

我的修改:

// Save the original `Date` function
const OriginalDate = Date;
const fakeDateArgs = [2022, 5, 3]; // beware month is 0 based
let fakeDate;
// Replace it with our own
Date = function Date(...args) {
    // Called via `new`?
    if (!new.target) {
        // No, just pass the call on
        return OriginalDate(...args);
    }
    // Determine what constructor to call
    const ctor = new.target === Date ? OriginalDate : new.target;
    // Called via `new`
    if (args.length !== 0) {
        // Date constructor arguments were provided, just pass through
        return Reflect.construct(ctor, args);
    }
    // It's a `new Date()` call, mock the date we want; in this
    fakeDate = Reflect.construct(ctor, fakeDateArgs);
    return fakeDate;
};
// Make our replacement look like the original (which has `length = 7`)
// You can't assign to `length`, but you can redefine it
Object.defineProperty(Date, "length", {
    value: OriginalDate.length,
    configurable: true
});

Object.defineProperty(Date, "now", {
    value: () => fakeDate.getTime(),
    configurable: true
});


0
投票

您可以在加载之前使用它来修改内容: https://developer.chrome.com/docs/extensions/reference/webRequest/

有一个我没有使用过的扩展也许可以做到这一点: https://chrome.google.com/webstore/detail/page-manipulator/mdhellggnoabbnnchkeniomkpghbekko?hl=en


0
投票

这里是在浏览器中模拟 Date 对象的实现。月份始终从零开始,默认日期设置为 2024 年 1 月 1 日,可以更改。这最好仅用于测试目的:

((originalDate) => {
    // Function to mock the Date object
    function MockDate(...args) {
        if (args.length) {
            return new originalDate(...args);
        }
        // Default date: January 1, 2024
        return new originalDate(2024, 0, 1);
    }

    MockDate.prototype = originalDate.prototype;
    MockDate.now = () => new MockDate().getTime();
    MockDate.UTC = originalDate.UTC;
    MockDate.parse = originalDate.parse;

    // Override the global Date object
    Date = MockDate;
})(Date);

可以通过以下方式进行测试:

console.log(new Date());
© www.soinside.com 2019 - 2024. All rights reserved.