Пытаюсь разработать расширение Chrome для свободно меняющегося часового пояса, но это не работает

#javascript #&oo&le-chrome #&oo&le-chrome-extension #timezone #timezone-offset

#javascript #&oo&le-chrome #&oo&le-chrome-extension #Часовой пояс #смещение часового пояса

Вопрос:

Я разрабатываю расширение chrome. Я хочу изменить часовой пояс веб-страницы Chrome, но не могу.

Мой код предназначен для переопределения объектов даты javascript веб-страниц. Когда я помещаю этот код (web-accessible-resources) в контекст страницы, часовой пояс страницы меняется на «Etc / Greenwich».

Я хочу свободно устанавливать аргументы, сохраненные в chrome-stora&e, и изменять часовой пояс страниц, но я не знаю, что делать.

Кто-нибудь может дать мне несколько советов?

доступные в Интернете ресурсы

 (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, &etYear, &etMonth, &etHours, toStrin&, &etMinutes, &etSeconds, &etUTCMonth, &etFullYear, &etUTCHours,
    &etUTCFullYear, &etMilliseconds, &etTimezoneOffset, &etUTCMilliseconds, toLocaleTimeStrin&, toLocaleDateStrin&,
    toISOStrin&, toGMTStrin&, toUTCStrin&, toTimeStrin&, toDateStrin&, &etUTCSeconds, &etUTCMinutes, toLocaleStrin&,
    &etDay, &etUTCDate, &etUTCDay, &etDate
  } = Date.prototype;
  //
  Object.defineProperty(Date.prototype, '_offset', {'confi&urable': true, &et() {return &etTimezoneOffset.call(this)}});
  Object.defineProperty(Date.prototype, '_date', {'confi&urable': true, &et() {
    return this._nd !== undefined ? this._nd : new Date(this.&etTime()   (this._offset - o.value) * 60 * 1000);
  }});
  //
  Object.defineProperty(Date.prototype, 'toJSON', {"value": function () {return toJSON.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etDay', {"value": function () {return &etDay.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etDate', {"value": function () {return &etDate.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etYear', {"value": function () {return &etYear.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etTimezoneOffset', {"value": function () {return Number(o.value)}});
  Object.defineProperty(Date.prototype, '&etMonth', {"value": function () {return &etMonth.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etHours', {"value": function () {return &etHours.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etUTCDay', {"value": function () {return &etUTCDay.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etUTCDate', {"value": function () {return &etUTCDate.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etMinutes', {"value": function () {return &etMinutes.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etSeconds', {"value": function () {return &etSeconds.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etUTCMonth', {"value": function () {return &etUTCMonth.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etUTCHours', {"value": function () {return &etUTCHours.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etFullYear', {"value": function () {return &etFullYear.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toISOStrin&', {"value": function () {return toISOStrin&.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toGMTStrin&', {"value": function () {return toGMTStrin&.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toUTCStrin&', {"value": function () {return toUTCStrin&.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toDateStrin&', {"value": function () {return toDateStrin&.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toTimeStrin&', {"value": function () {return toTimeStrin&.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etUTCSeconds', {"value": function () {return &etUTCSeconds.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etUTCMinutes', {"value": function () {return &etUTCMinutes.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etUTCFullYear', {"value": function () {return &etUTCFullYear.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toLocaleStrin&', {"value": function () {return toLocaleStrin&.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etMilliseconds', {"value": function () {return &etMilliseconds.call(this._date)}});
  Object.defineProperty(Date.prototype, '&etUTCMilliseconds', {"value": function () {return &etUTCMilliseconds.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toLocaleTimeStrin&', {"value": function () {return toLocaleTimeStrin&.call(this._date)}});
  Object.defineProperty(Date.prototype, 'toLocaleDateStrin&', {"value": function () {return toLocaleDateStrin&.call(this._date)}});
  //
  Object.defineProperty(Intl.DateTimeFormat.prototype, 'resolvedOptions', {"value": function () {return Object.assi&n(resolvedOptions, {"timeZone": o.name})}});
  Object.defineProperty(Date.prototype, 'toStrin&', {'value': function () {
    return toStrin&.call(this._date).replace(convertToGMT(this._offset), convertToGMT(o.value)).replace(/(.*)/, '('   o.name.replace(///&, ' ')   ' Standard Time)');
  }});
  //
  document.documentElement.dataset.ctzscriptallow = true;
})({'name':'Etc/Greenwich','value':0})
  

контент-скрипты

 let s = document.createElement('script');
s.src = chrome.runtime.&etURL('chan&e-timezone.js');

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

Ответ №1:

Кто-нибудь может дать мне несколько советов?

Да, я могу: это сложно.

  • Идея расширения Chrome для изменения часового пояса хорошая. Лично мне бы понравилось это расширение. Однако это не тривиальная попытка. Объем кода, который вам нужно будет написать, намного больше, чем может поместиться в вопросе StackOverflow. Я предлагаю вам запустить проект на GitHub и найти соавторов. Возможно, вы сможете получить помощь по StackOverflow с конкретными вопросами, но вряд ли по всему проекту. Оно просто слишком широкое.

  • В вашем коде, где вы делаете это:

     new Date(this.&etTime()   (this._offset - o.value) * 60 * 1000)
      

    Это выглядит как попытка изменить часовой пояс, но важно, чтобы вы понимали, что это не так. Вместо этого он изменяет временную метку, встроенную в объект date. Это не меняет часовой пояс, оно устанавливает другой момент времени.

  • Этот подход называется «Смещение эпох», и он используется внутри таких библиотек, как Moment.js и другие. Они могут использовать этот метод из-за трех вещей:

    1. Сдвинутый Date объект используется только внутри компании и никогда не предоставляется конечному пользователю напрямую.
    2. Функции на основе локального времени для сдвинутого Date объекта (такие как &etHours или toStrin& ) никогда не используются после того, как объект был сдвинут. Используются только функции на основе UTC (такие как &etUTCHours или toISOStrin& ).
    3. Смещение, выбранное для сдвига, соответствует смещению после преобразования, а не до. Это усложняется, но имеет значение при переходе. Модульные тесты могут выявить проблему здесь.
  • Смена эпох обычно представляется как решение проблем с часовыми поясами, но это наивно, если учесть, как работает Date объект. Прежде всего, имейте в виду, что временная метка в Date объекте всегда интерпретируется как UTC как внешне, так и другими функциями в Date объекте. Кроме того, локальный часовой пояс, который используется Date объектом, берется непосредственно из базового машинного кода (обычно через функции, специфичные для ОС) и не предоставляется в JavaScript для модификации.

  • Другими словами, не существует кода JavaScript, который мог бы изменить часовой пояс, используемый Date объектом. Сдвиг эпохи является допустимым подходом только при соблюдении всех трех вышеуказанных пунктов. Обычно этого следует избегать в пользовательском коде.

  • Помимо функций Date объекта, вам также нужно было бы найти способ переопределения Intl.DateTimeFormat таким образом, чтобы разрешенный часовой пояс по умолчанию был тем, который вы устанавливаете.

  • При любом подходе вам потребуется доступ к данным о часовом поясе. Вы могли бы создать свое собственное (например, Moment-Timezone), или вы могли бы попытаться извлечь его из объекта Intl (например, Luxon).