尝试开发Chrome扩展来自由更改时区,但它不起作用

2023-12-12

我正在开发 chrome 扩展。 我想更改 Chrome 网页的时区,但不能。

我的代码用于覆盖网页 javascript 日期对象。 当我将此代码(网络可访问资源)放入页面上下文中时,页面的时区更改为“Etc/Greenwich”。

我想自由设置保存在 chrome-storage 中的参数并更改页面时区, 但我不知道该怎么办。

谁能给我一些建议吗?

网络可访问资源

(function (o) {
  const convertToGMT = function (n) {
    const format = function (v) {return (v < 10 ? '0' : '') + v};
    return (n <= 0 ? '+' : '-') + format(Math.abs(n) / 60 | 0) + format(Math.abs(n) % 60);
  };
  //
  const resolvedOptions = Intl.DateTimeFormat().resolvedOptions();
  const {
    toJSON, getYear, getMonth, getHours, toString, getMinutes, getSeconds, getUTCMonth, getFullYear, getUTCHours,
    getUTCFullYear, getMilliseconds, getTimezoneOffset, getUTCMilliseconds, toLocaleTimeString, toLocaleDateString,
    toISOString, toGMTString, toUTCString, toTimeString, toDateString, getUTCSeconds, getUTCMinutes, toLocaleString,
    getDay, getUTCDate, getUTCDay, getDate
  } = Date.prototype;
  //
  Object.defineProperty(Date.prototype, '_offset', {'configurable': true, get() {return getTimezoneOffset.call(this)}});
  Object.defineProperty(Date.prototype, '_date', {'configurable': true, get() {
    return this._nd !== undefined ? this._nd : new Date(this.getTime() + (this._offset - o.value) * 60 * 1000);
  }});
  //
  Object.defineProperty(Date.prototype, 'toJSON', {"value": function () {return toJSON.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getDay', {"value": function () {return getDay.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getDate', {"value": function () {return getDate.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getYear', {"value": function () {return getYear.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getTimezoneOffset', {"value": function () {return Number(o.value)}});
  Object.defineProperty(Date.prototype, 'getMonth', {"value": function () {return getMonth.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getHours', {"value": function () {return getHours.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getUTCDay', {"value": function () {return getUTCDay.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getUTCDate', {"value": function () {return getUTCDate.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getMinutes', {"value": function () {return getMinutes.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getSeconds', {"value": function () {return getSeconds.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getUTCMonth', {"value": function () {return getUTCMonth.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getUTCHours', {"value": function () {return getUTCHours.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getFullYear', {"value": function () {return getFullYear.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toISOString', {"value": function () {return toISOString.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toGMTString', {"value": function () {return toGMTString.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toUTCString', {"value": function () {return toUTCString.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toDateString', {"value": function () {return toDateString.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toTimeString', {"value": function () {return toTimeString.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getUTCSeconds', {"value": function () {return getUTCSeconds.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getUTCMinutes', {"value": function () {return getUTCMinutes.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getUTCFullYear', {"value": function () {return getUTCFullYear.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toLocaleString', {"value": function () {return toLocaleString.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getMilliseconds', {"value": function () {return getMilliseconds.call(this._date)}});
  Object.defineProperty(Date.prototype, 'getUTCMilliseconds', {"value": function () {return getUTCMilliseconds.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toLocaleTimeString', {"value": function () {return toLocaleTimeString.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toLocaleDateString', {"value": function () {return toLocaleDateString.call(this._date)}});
  //
  Object.defineProperty(Intl.DateTimeFormat.prototype, 'resolvedOptions', {"value": function () {return Object.assign(resolvedOptions, {"timeZone": o.name})}});
  Object.defineProperty(Date.prototype, 'toString', {'value': function () {
    return toString.call(this._date).replace(convertToGMT(this._offset), convertToGMT(o.value)).replace(/\(.*\)/, '(' + o.name.replace(/\//g, ' ') + ' Standard Time)');
  }});
  //
  document.documentElement.dataset.ctzscriptallow = true;
})({'name':'Etc/Greenwich','value':0})

内容脚本

let s = document.createElement('script');
s.src = chrome.runtime.getURL('change-timezone.js');

s.onload = function() {
  this.remove();
};
(document.head || document.documentElement).appendChild(s);

谁能给我一些建议吗?

我可以:这是困难的。

  • The ideaChrome 扩展程序可以更改时区,这是一个很好的扩展。我个人会喜欢这个扩展。然而,它是not一项微不足道的努力。您需要编写的代码量比 StackOverflow 问题所能容纳的代码量要大得多。我建议你启动一个 GitHub 项目并寻找合作者。您也许可以在 StackOverflow 上获得有关特定问题的帮助,但不太可能获得整个项目的帮助。它太宽泛了。

  • 在您的代码中执行此操作的位置:

    new Date(this.getTime() + (this._offset - o.value) * 60 * 1000)
    

    这看起来像是试图更改时区,但重要的是您要了解事实并非如此。它所做的是更改日期对象中嵌入的时间戳。这不会改变时区,它设置了不同的时间点.

  • 这种方法称为“Epoch Shifting”,由 Moment.js 等库在内部使用。他们之所以可以使用这种技术,是因为以下三点:

    1. 转移的Date对象仅在内部使用,从不直接暴露给最终用户。
    2. 基于本地时间的函数Date对象(例如getHours or toString)一旦对象被移动就永远不会被使用。仅基于 UTC 的函数(例如getUTCHours or toISOString)被使用。
    3. 选择移动的偏移量是after转换,而不是之前。这变得很复杂,但在过渡附近很重要。单元测试可以揭示这里的挑战。
  • Epoch Shifting 通常被认为是时区问题的一种解决方案,但当人们考虑如何解决时区问题时,这是天真的。Date对象有效。首先,请记住,时间戳Date对象是always在外部和内部的其他函数中均解释为 UTCDate目的。此外,所使用的本地时区Date对象直接来自底层本机代码(通常通过操作系统特定的函数),并且不会暴露到 JavaScript 中进行修改。

  • 换句话说,没有任何 JavaScript 代码可以更改系统所在的时区。Date对象使用。仅当满足上述所有三点时,Epoch Shifting 才是一种有效的方法。通常应在用户代码中避免使用它。

  • 除了Date对象的功能,你还必须找到一种方法来覆盖Intl.DateTimeFormat这样默认解析的时区就是您正在设置的时区。

  • 无论采用哪种方法,您都需要访问时区数据。您可以自带(例如 Moment-Timezone 所做的),或者您可以尝试从 Intl 对象中提取它(例如 Luxon 所做的)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试开发Chrome扩展来自由更改时区,但它不起作用 的相关文章