how long ago

replaces all dates with the time from that date

当前为 2025-01-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name how long ago
  3. // @version 4
  4. // @description replaces all dates with the time from that date
  5. // @run-at document-end
  6. // @author rssaromeo
  7. // @license GPLv3
  8. // @match *://*/*
  9. // @tag laggy
  10. // @tag style
  11. // @exclude /^https?:\/\/[^\/]*livereload.net\/files\/ffopen\/index\.html$/
  12. // @exclude /^https?:\/\/[^\/]*stackblitz.com/
  13. // @exclude /^https?:\/\/[^\/]*webcontainer.io/
  14. // @exclude /^https?:\/\/[^\/]*regexr.com/
  15. // @exclude /^https?:\/\/[^\/]*regex101.com/
  16. // @exclude *://*/*.mjs
  17. // @exclude *://*/*.js
  18. // @exclude *://*/*.css
  19. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHJQTFRFAAAAEIijAo2yAI60BYyuF4WaFIifAY6zBI2wB4usGIaZEYigIoiZCIyrE4igG4iYD4mjEomhFoedCoqpDIqnDomlBYyvE4efEYmiDYqlA42xBoytD4mkCYqqGYSUFYidC4qoC4upAo6yCoupDYqmCYur4zowOQAAACZ0Uk5TAO////9vr////1+/D/+/L+/Pf/////+f3///////H4////////+5G91rAAACgUlEQVR4nM2Y22KjIBCGidg1264liZqDadK03X3/V2wNKHMC7MpF/xthHD5mgERAqZhWhfYqH6K+Qf2qNNf625hCoFj9/gblMUi5q5jLkXLCKudgyiRm0FMK82cWJp1fLbV5VmvJbCIc0GCYaFqqlDJgADdBjncqAXYobm1xh72aFMflbysteFfdy2Yi1XGOm5HGBzQ1dq7TzEoxjeNTjQZb7VA3e1c7+ImgasAgQ9+xusNVNZIo5xmOMgihIS2PbCQIiHEUdTvhxCcS/kPomfFI2zHy2PkWmA6aNatIJpKFJyekyy02xh5Y3DI9T4aOT6VhIUrsNTFp1pf79Z4SIIVDegl6IJO6cHiL/GimIZDhgTu/BlYWCQzHMl0zBWT/T3KAhtxOuUB9FtBrpsz0RV4xsjHmW+UCaffcSy/5viMGer0/6HdFNMZBq/vjJL38H9Dqx4Fuy0Em12DbZy+9pGtiDijbglwAehyj11n0tRD3WUBm+lwulE/8h4BuA+iWAQQnteg2Xm63WQLTpnMnpjdge0Mgu/GRPsV4xdjQ94Lfi624fabhDkfUqIKNrM64Q837v8yL0prasepCgrtvw1sJpoqanGEX7b5mQboNW8eawXaWXTMfMGxub472hzWzHSn6Sg2G9+6TAyRruE71s+zAzjWaknoyJCQzwxrghH2k5FDT4eqWunuNxyN9QCGcxVod5oADbYnIUkDTGZEf1xDJnSFteQ3KdsT8zYDMQXcHxsevcLH1TrsABzkNPyA/L7b0jg704viMMlpQI96WsHknCt/3YH0kOEo9zcGkwrFK39ck72rmoehmKqo2RKlilzSy/nJKEV45CT38myJp456fezktHjN5aeMAAAAASUVORK5CYII=
  20. // @grant none
  21. // @namespace https://greasyfork.org/users/1184528
  22. // ==/UserScript==
  23. const a = loadlib("allfuncs")
  24. const newelem = loadlib("newelem")
  25. const replacements = [
  26. [
  27. "monthname",
  28. "(?:jan(?:uary)?|feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|may|june?|july?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)",
  29. ],
  30. [
  31. "month",
  32. "(?:\\d{1,2}|(?:jan(?:uary)?|feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|may|june?|july?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?))",
  33. ],
  34. ["day", "\\d{1,2}(?:rd|th|nd|st)?"],
  35. ["year", "\\d{4}(?:rd|th|nd|st)?"],
  36. ["space", "[^a-z0-9.]"],
  37. ["start", "(?<![\\d\\w])"],
  38. ["end", "(?![\\d\\w])"],
  39. ["d2", "\\d{2}(?:rd|th|nd|st)?"],
  40. ["d4", "\\d{4}(?:rd|th|nd|st)?"],
  41. ["d12", "\\d{1,2}(?:rd|th|nd|st)?"],
  42. ]
  43.  
  44. const formats = [
  45. { regex: "start(month)space(day)space(year)end", order: [2, 1, 3] },
  46. { regex: "start(year)[-/](month)[-/](day)end", order: [3, 2, 1] },
  47. ].map((e) => {
  48. let reg = e.regex
  49. const order = e.order
  50. replacements.forEach(([pattern, replacement]) => {
  51. reg = reg.replaceAll(pattern, replacement)
  52. })
  53.  
  54. return { regex: new RegExp(reg, "gi"), order }
  55. })
  56. log(formats, formats[0].regex)
  57. const tonum = {
  58. january: 1,
  59. february: 2,
  60. march: 3,
  61. april: 4,
  62. may: 5,
  63. june: 6,
  64. july: 7,
  65. august: 8,
  66. september: 9,
  67. october: 10,
  68. november: 11,
  69. december: 12,
  70. jan: 1,
  71. feb: 2,
  72. mar: 3,
  73. apr: 4,
  74. jun: 6,
  75. jul: 7,
  76. aug: 8,
  77. sep: 9,
  78. oct: 10,
  79. nov: 11,
  80. dec: 12,
  81. }
  82.  
  83. const dateRegex =
  84. /(\d{1,4}[-/]\d{1,2}[-/]\d{1,4}|\w+\s+\d{1,2},?\s+\d{4}|\d{1,2}\s+\w+\s+\d{4}|.+)/gi
  85. function processDatesinElement(elem) {
  86. if (elem.processed) return
  87. if (elem.nodeType === Node.TEXT_NODE) {
  88. if (elem.innerHTML.includes("☺"))return
  89. let newContent = elem.textContent.replace(dateRegex, (match) => {
  90. let x = getdate(match)
  91. return x ? getstr(x) : match
  92. })
  93. if (newContent !== elem.textContent) {
  94. elem.textContent = newContent
  95. elem.processed = true
  96. debugger
  97. console.log(123123123123, elem)
  98. }
  99. } else {
  100. if (elem.title && !elem.title.includes("☺")) {
  101. let x = getdate(elem.title)
  102. if (x) elem.title = elem.title.replace(x.string, getstr(x))
  103. }
  104.  
  105. if (elem.tagName.toLowerCase() === "relative-time") {
  106. if (!elem.shadowRoot || elem.shadowRoot.innerHTML.includes("☺")) return
  107. elem = elem.shadowRoot
  108. }
  109. }
  110.  
  111. elem.processed = true
  112. }
  113. ;[...document.body.childNodes]
  114. .filter((e) => e.nodeType === Node.ELEMENT_NODE)
  115. .forEach(processDatesinElement)
  116. a(processDatesinElement).runonallelems("*", ["STYLE", "SCRIPT", "NOSCRIPT"])
  117. function getdate(date) {
  118. if (!getdate.cache) getdate.cache = new Map()
  119. if (getdate.cache.has(date)) return getdate.cache.get(date)
  120.  
  121. const result = parseDate(date)
  122. getdate.cache.set(date, result)
  123. return result
  124. }
  125.  
  126. function parseDate(date) {
  127. for (const format of formats) {
  128. const match = [...date.matchAll(format.regex)][0]
  129. if (match) {
  130. const [day, month, year] = format.order.map((i) => match[i])
  131. return createDateObject(day, month, year, match[0])
  132. }
  133. }
  134.  
  135. return null
  136. }
  137.  
  138. function createDateObject(day, month, year, string) {
  139. day = parseInt(day, 10)
  140. month = tonum[month.toLowerCase()] || parseInt(month, 10)
  141. year = parseInt(year, 10)
  142. if (year < 100) year += 2000
  143.  
  144. if (!month || day > 31) return null
  145.  
  146. const date = new Date(year, month - 1, day)
  147. const today = new Date()
  148. today.setHours(0, 0, 0, 0)
  149. const ms = today - date
  150.  
  151. return {
  152. day,
  153. month,
  154. year,
  155. string,
  156. ms: Math.abs(ms),
  157. isago: ms > 0,
  158. }
  159. }
  160.  
  161. function howlongago(ms) {
  162. const units = [
  163. { name: "year", ms: 31536000000 },
  164. { name: "week", ms: 604800000 },
  165. { name: "day", ms: 86400000 },
  166. { name: "hour", ms: 3600000 },
  167. { name: "minute", ms: 60000 },
  168. { name: "second", ms: 1000 },
  169. ]
  170.  
  171. let result = []
  172. for (const unit of units) {
  173. const value = Math.floor(ms / unit.ms)
  174. if (value > 0) {
  175. result.push(`${value} ${unit.name}${value !== 1 ? "s" : ""}`)
  176. ms %= unit.ms
  177. }
  178. if (result.length >= 2) break
  179. }
  180.  
  181. return result.length ? result.join(" ") : "today"
  182. }
  183.  
  184. function getstr(x) {
  185. return `[${howlongago(x.ms)} ${
  186. howlongago(x.ms) == "today" ? "" : x.isago ? "ago" : "until"
  187. } ${x.string}☺]`
  188. }