您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
即时将外国时间转换为本地时间。
// ==UserScript== // @name WorldTime Whisperer // @name:de WorldTime-Flüsterer // @name:es Susurrador de Horas Globales // @name:fr Chuchoteur de Fuseaux Horaires // @name:it Sussurratore del Tempo Mondiale // @name:ru Шептун Мирового Времени // @name:zh-CN 世界时间耳语者 // @name:zh-TW 世界時間耳語者 // @name:ja ワールドタイム・ウィスパラー // @name:ko 세계 시간 속삭임이 // @name:hi वर्ल्डटाइम विस्परर // @name:ar همس الوقت العالمي // @name:he לוחש הזמן העולמי // @name:sv Världstidviskaren // @name:nl Wereldtijdfluisteraar // @name:pt Sussurrador do Tempo Mundial // @namespace https://greasyfork.org/en/users/1451802 // @version 1.1 // @description Turns foreign times into familiar ones, instantly. // @description:de Wandelt fremde Zeiten sofort in deine lokale Zeit um. // @description:es Convierte tiempos extranjeros en horas locales al instante. // @description:fr Transforme instantanément les heures étrangères en heures locales. // @description:it Converte istantaneamente gli orari stranieri in orari locali. // @description:ru Мгновенно превращает чужое время в ваше местное. // @description:zh-CN 即时将外国时间转换为本地时间。 // @description:zh-TW 即時將外國時間轉換為本地時間。 // @description:ja 外国の時間を瞬時にあなたの現地時間に変換します。 // @description:ko 해외 시간을 즉시 현지 시간으로 변환합니다. // @description:hi विदेशी समय को तुरंत स्थानीय समय में बदलता है। // @description:ar يحول الأوقات الأجنبية إلى وقتك المحلي فورًا. // @description:he ממיר מיד זמנים זרים לשעה המקומית שלך. // @description:sv Förvandlar främmande tider till lokal tid direkt. // @description:nl Zet buitenlandse tijden onmiddellijk om naar je lokale tijd. // @description:pt Converte horários estrangeiros para o seu local instantaneamente. // @match *://*/* // @grant none // @license MIT // @icon https://www.svgrepo.com/show/476947/timezone.svg // @author NormalRandomPeople (https://github.com/NormalRandomPeople) // @compatible chrome // @compatible firefox // @compatible opera // @compatible edge // @compatible brave // ==/UserScript== (function () { 'use strict'; const timezoneOffsets = { "PST": -8, "PDT": -7, "MST": -7, "MDT": -6, "CST": -6, "CDT": -5, "EST": -5, "EDT": -4, "UTC": 0, "GMT": 0, "BST": 1, "CET": 1, "CEST": 2, "EET": 2, "EEST": 3, "IST": 5.5, "JST": 9, "AEST": 10,"AEDT": 11,"ACST": 9.5, "ACDT": 10.5 }; const localTimeMessages = { "en": "Local time:", "de": "Ortszeit:", "fr": "Heure locale:", "es": "Hora local:", "it": "Ora locale:", "pt": "Hora local:", "nl": "Lokale tijd:", "sv": "Lokal tid:", "ru": "Местное время:", "ja": "現地時間:", "zh": "本地时间:", "ko": "현지 시간:", "hi": "स्थानीय समय:", "ar": "الوقت المحلي:", "he": "שעה מקומית:" }; const rtlLangs = ["ar", "he", "fa", "ur"]; const langPrefix = (navigator.language || navigator.userLanguage || "en").slice(0, 2).toLowerCase(); const isRTL = rtlLangs.includes(langPrefix); const timeLabel = localTimeMessages[langPrefix] ?? "Local time:"; const formatter = new Intl.DateTimeFormat(navigator.language, { hour: 'numeric', minute: '2-digit', second: '2-digit', hour12: undefined }); const timeRegex = /(\b\d{1,2})(?:[:.](\d{2}))?(?:[:.](\d{2}))?\s*(AM|PM)?\s*([A-Za-z]{2,4})\b/gi; function convertTime(match, h, m, s, period, tz) { tz = tz.toUpperCase(); if (!(tz in timezoneOffsets)) return match; let hour = parseInt(h, 10); let minute = parseInt(m || "0", 10); let second = parseInt(s || "0", 10); if (period) { period = period.toUpperCase(); if (period === "PM" && hour !== 12) hour += 12; if (period === "AM" && hour === 12) hour = 0; } const offsetMs = timezoneOffsets[tz] * 60 * 60 * 1000; const now = new Date(); const sourceUtcMs = Date.UTC( now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), hour, minute, second ); const localDate = new Date(sourceUtcMs - offsetMs); const formatted = formatter.format(localDate); return isRTL ? `(${timeLabel} ${formatted}) ${match}` : `${match} (${timeLabel} ${formatted})`; } function walk(node) { if (node.nodeType === 3) { const original = node.nodeValue; const updated = original.replace(timeRegex, convertTime); if (updated !== original) node.nodeValue = updated; } else if ( node.nodeType === 1 && !['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA'].includes(node.tagName) ) { for (let child = node.firstChild; child; child = child.nextSibling) { walk(child); } } } walk(document.body); new MutationObserver(mutations => { mutations.forEach(m => { m.addedNodes.forEach(n => walk(n)); }); }).observe(document.body, { childList: true, subtree: true }); })();