日期绿色
// ==UserScript==
// @name 日期改色
// @namespace http://tampermonkey.net/
// @version 1.3
// @description 日期绿色
// @author ChenHongJiang
// @match *://*/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// '',// 👉
// 定义日期格式的正则表达式
// 空格 ' +kg+ '
const kg = '(?: |\\s*)?';
// 前后非数字 ' +noNum+ '
const noNum = '(?!\\d)';
// 汉字数字 ' +hanNum+ '
const hanNum = '(?:十|二十|三十|四十|五十|六十|七十|八十|九十)?(?:一|单|單|兩|两|二|三|四|两|五|六|七|八|九|十)';
// 量词 ' +liangCi+ '
const liangCi = '(?:亿万|万亿|千亿|百亿|十亿|千万|百万|十万|億萬|萬億|千億|百億|十億|千萬|百萬|十萬|萬|億|亿|万|千|百|十|\\+)?';
// 前面词 2000 ' +qmcEN+ '
const qmcEN = '(?:in|to|for|into|of|by|since|at|on|with|from|about|through|over|under|between|among|across|toward|towards|against|beside|before|after|except|including|like|without|year|trends)';
const datePatterns = [
noNum+ '\\d{4}' +noNum +kg+ '(?:-|.)' +kg+ noNum+ '\\d{2}' +noNum +kg+ '(?:-|.)' +kg+ noNum+ '\\d{2}' +noNum, // 👉 0000-00-00
'\\b\\d{4}' +kg+ '-' +kg+ '\\d{2}' +kg+ '-' +kg+ '\\d{2}\\b', // 👉 0000-00-00
'(截(?:至|止))?\\d+' +kg+ '年' +kg+ '\\d+' +kg+ '月' +kg+ '\\d+' +kg+ '日', // 👉 0000年00月00日
'\\d+' +kg+ '年' +kg+ '\\d+' +kg+ '(?:月)?' +kg+ '(?:-|~)' +kg+ '\\d+月', // 👉 0000年00-00月
'\\d+' +kg+ '(?:年|月)' +kg+ '\\d+' +kg+ '(?:月|日)', // 👉 0000年00月
'(?:(\\d+)|(?:上个|最新|春节|今|去|前|明|本))' +kg+ '年?' +kg+ '第?' +hanNum+ '?个?(?:季度|多月|月份)', // 👉 0000年一季度
'\\b' +noNum+ '\\d{1,2}' +noNum +kg+ '-' +kg+ noNum+ '\\d{1,2}' +kg+ '(?=\\s|$)', // 👉 00-00
'(?:(截(?:至|止))|(?:前年|今年|明年))?' +kg+ '(?:(\\d{1,12})|' +hanNum+ ')' +kg+ '月'+kg+ '(?:(\\d{1,12})|' +hanNum+ ')?' +kg+ '(?:日|底|号)?', // 今年0月0日
noNum+ '(?:\\d{2}|\\d{4})' +kg+ '(?:财年|年)?' +kg+ '(?:-|~|、|—|to|至|到)' +kg+ '(?:\\d{2}|\\d{4})' +noNum +kg+ '(?:财年|年|个月|月)?', //👉 0000年 - 0000年
'\\d+' +kg+ '(?:财年|年)?' +kg+ '((?:Q|H)\\d+)', // 👉 0000年Q1
'(?:过去|最近|未来|那|这|上|下)?' +kg+ '(?:7(?:x|X|×))?(?:\\d{1,4}|' +hanNum+ ')' +kg+ liangCi+ '(?:周年|财年|年底|小时|分钟|个月|月份|(?:世纪|年代)|月|天|分|周|年|秒|点)' +kg+ '(?:之前|前|来|(?:中期|初|中|末))?', // 👉 0000 年
'(?:\\b)?(?:昨天|今天)' +kg+ '(?:\\d{1}' +noNum+ '|\\d{2}' +noNum+ ')' +kg+ '(?:(:)|:)' +kg+ '(?:\\d{1}' +noNum+ '|\\d{2}' +noNum+ ')', // 👉 昨/今天 00:00
'(?:\\b)?(?:\\d+)?(?:(?:前|昨|今|大后|后)天|(?:上|下)?半年|最近|近' +hanNum+ '年(半)?|(?:中上|中下|上|下|本|下|上)(?:季度|财年|午)|(?:近|长|中)期|短期内|(?:当|次)(?:季|月|年|日)|(?:年|季|月|旬)(?:初|中|末)|(?:近|长)期趋势|(?:短|长|中)期(?:波动|增长|调整|稳定)|(?:季节|周期)性|(?:年|季|月|周|日)度)|' +hanNum+ '岁',// 👉 前天,补漏单独词
'(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)' +kg+ '[A-Za-z]' +kg+ '\\d{1,2},' +kg+ '\\d{4}' +kg+ '(?=\\s|$)', // 👉 Wed April 30, 2025
'(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|January|February|March|April|May|June|July|August|September|October|November|December|early)' +kg+ '\\d{1,2}' +kg+ ',' +kg+ '\\d{4}',// 👉 May 05, 2025
'\\d{1,2}?' +kg+ '(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|January|February|March|April|May|June|July|August|September|October|November|December|early)' +kg+ '\\d{4}',// 👉 26 February 2024
'Q\\d+' +kg+ '\\d{4}' +noNum,// 👉 Q4 2023
qmcEN +kg+ '\\d{4}(?!.)' +noNum,// 👉 in 2024
'q' +kg+ '\\d+' +kg+ qmcEN +kg+ '\\d{4}' +noNum,// 👉 Q4 of 2023
'\\d+' +kg+ '(?:\\+)?' +kg+ '(?:min|minute)', // 10 min
];
const dateFormatRegex = new RegExp(datePatterns.join('|'), 'gi');
// 亮绿:#6bd167✔ 暗绿:#338143 英伟达绿:#76B900 鼠标绿:#BFFF00 微信绿:#52CE42✔ 沉浸式翻译绿:#67CC51✔ 鹦鹉绿:#5bae23✔
// #41b349 #43b244 #41ae3c
// 定义要应用的样式
const style = `
color: #5bae23 !important;
font-weight: 600 !important;
font-family: "Microsoft YaHei" !important;
text-shadow: none !important;
`;
// 遍历页面中所有的元素
const elements = document.querySelectorAll('*');
setTimeout(() => {
elements.forEach(element => {
// 获取元素的所有文本节点
const textNodes = getTextNodes(element);
// 遍历每个文本节点
textNodes.forEach(textNode => {
// 检查文本内容是否包含日期格式
if (dateFormatRegex.test(textNode.nodeValue)) {
// 匹配所有日期格式
const matches = textNode.nodeValue.match(dateFormatRegex);
// 从后向前处理每个匹配项
for (let i = matches.length - 1; i >= 0; i--) {
const match = matches[i];
const index = textNode.nodeValue.indexOf(match);
// 创建一个新 <font> 元素
const span = document.createElement('font');
span.style.cssText = style;
span.textContent = match;
// 使用 Range 来分割文本节点
const range = new Range();
range.setStart(textNode, index);
range.setEnd(textNode, index + match.length);
// 替换匹配的文本节点部分
range.deleteContents();
range.insertNode(span);
}
}
});
});
}, 1000); // 延迟 0.5 秒
// 获取元素的所有文本节点
function getTextNodes(node) {
const textNodes = [];
if (node.nodeType === Node.TEXT_NODE) {
textNodes.push(node);
} else if (node.nodeType === Node.ELEMENT_NODE) {
for (let child of node.childNodes) {
textNodes.push(...getTextNodes(child));
}
}
return textNodes;
}
})();