Absolute Time on GreasyFork

Make Absolute Time on GreasyFork

  1. // ==UserScript==
  2. // @name Absolute Time on GreasyFork
  3. // @namespace UserScript
  4. // @match https://gf.qytechs.cn/*
  5. // @grant none
  6. // @version 1.1.0
  7. // @license MIT
  8. // @author CY Fung
  9. // @description Make Absolute Time on GreasyFork
  10. // @unwrap
  11. // @run-at document-end
  12. // ==/UserScript==
  13.  
  14. (() => {
  15.  
  16. let langUsed = null;
  17.  
  18. const Promise = (async () => { })().constructor;
  19.  
  20. const PromiseExternal = ((resolve_, reject_) => {
  21. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  22. return class PromiseExternal extends Promise {
  23. constructor(cb = h) {
  24. super(cb);
  25. if (cb === h) {
  26. /** @type {(value: any) => void} */
  27. this.resolve = resolve_;
  28. /** @type {(reason?: any) => void} */
  29. this.reject = reject_;
  30. }
  31. }
  32. };
  33. })();
  34.  
  35. function pad(s, d) {
  36. s = `000000${s}`
  37. return s.substring(s.length - d)
  38. }
  39.  
  40. /**
  41. * @callback formatDateTimeFn
  42. * @param {DateTime} dt
  43. * @returns {string} formated text for date & time
  44. */
  45.  
  46. /** @type {formatDateTimeFn} */
  47. const formatUFn = (dt) => {
  48. return `${dt.getFullYear()}.${pad(dt.getMonth() + 1, 2)}.${pad(dt.getDate(), 2)} ${pad(dt.getHours(), 2)}:${pad(dt.getMinutes(), 2)}`
  49.  
  50. }
  51.  
  52. /** @type {formatDateTimeFn} */
  53. const formatFrFn = (dt) => {
  54. return `${pad(dt.getDate(), 2)}.${pad(dt.getMonth() + 1, 2)}.${dt.getFullYear()} ${pad(dt.getHours(), 2)}:${pad(dt.getMinutes(), 2)}`
  55. }
  56.  
  57. let formatFn = formatUFn;
  58.  
  59. let rafPromise = null;
  60.  
  61. const getRafPromise = () => rafPromise || (rafPromise = new Promise(resolve => {
  62. requestAnimationFrame(hRes => {
  63. rafPromise = null;
  64. resolve(hRes);
  65. });
  66. }));
  67.  
  68. let delay100 = null;
  69.  
  70. delay100 = new PromiseExternal();
  71. setInterval(() => {
  72. delay100.resolve();
  73. delay100 = new PromiseExternal();
  74. }, 100);
  75.  
  76. let psk = 0;
  77.  
  78. const cssText = `
  79.  
  80. @keyframes relativeTimeNotAbsoluteAppended {
  81. from{
  82. background-position-x: 1px;
  83. }
  84. to{
  85. background-position-x: 2px;
  86. }
  87. }
  88. relative-time[datetime]:not(.absolute) {
  89. animation: relativeTimeNotAbsoluteAppended 1ms linear 0s 1 normal forwards;
  90. }
  91.  
  92. `;
  93.  
  94. async function fixRelativeTime(s) {
  95.  
  96. psk = Date.now();
  97.  
  98. s.classList.add("absolute")
  99. s.format = 'datetime';
  100. await Promise.resolve().then();
  101. await getRafPromise().then();
  102.  
  103. if (langUsed === null) {
  104. langUsed = document.documentElement.lang;
  105. if (typeof langUsed === 'string' && (langUsed === 'fr' || langUsed.startsWith('fr-'))) {
  106. formatFn = formatFrFn;
  107. }
  108. }
  109.  
  110. let d = s.getAttribute('datetime');
  111. let dt = d ? new Date(d) : null;
  112. if (dt && s.shadowRoot && s.shadowRoot.firstChild) {
  113.  
  114. psk = Date.now();
  115. while (Date.now() - psk < 800) {
  116. s.shadowRoot.firstChild.textContent = formatFn(dt);
  117. await delay100.then();
  118. }
  119.  
  120. }
  121.  
  122. }
  123.  
  124. document.addEventListener('animationstart', (evt) => {
  125. const animationName = evt.animationName;
  126. if (!animationName) return;
  127. if (animationName === 'relativeTimeNotAbsoluteAppended') {
  128. fixRelativeTime(evt.target);
  129. }
  130. }, { capture: true, passive: true });
  131.  
  132. document.head.appendChild(document.createElement('style')).textContent = cssText;
  133.  
  134. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址