Discord Timestamp with Seconds

This script provides users with the capability to view seconds in the timestamps of Discord messages, allows users to view the time that has elapsed since a message was sent, and enhances the date formatting.

  1. // ==UserScript==
  2. // @name Discord Timestamp with Seconds
  3. // @namespace http://tampermonkey.net/
  4. // @version 3.4
  5. // @description This script provides users with the capability to view seconds in the timestamps of Discord messages, allows users to view the time that has elapsed since a message was sent, and enhances the date formatting.
  6. // @author Sam (and ChatGPT lol; yes, ChatGPT helped me with this. With the help of many others listed on the "History" section of the GreasyFork page of this script. (https://greasyfork.org/en/scripts/462588-discord-timestamp-with-seconds-and-date)
  7. // @match https://discord.com/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // Function to format the timestamp with seconds in 12-hour format
  16. function formatTimestampWithSeconds12Hour(datetime) {
  17. const date = new Date(datetime);
  18. const hours = date.getHours() % 12 || 12;
  19. const minutes = date.getMinutes().toString().padStart(2, '0');
  20. const seconds = date.getSeconds().toString().padStart(2, '0');
  21. const ampm = date.getHours() >= 12 ? 'PM' : 'AM';
  22. return `${hours}:${minutes}:${seconds} ${ampm}`;
  23. }
  24.  
  25. // Function to format the timestamp with seconds in 24-hour format
  26. function formatTimestampWithSeconds24Hour(datetime) {
  27. const date = new Date(datetime);
  28. const hours = date.getHours().toString().padStart(2, '0');
  29. const minutes = date.getMinutes().toString().padStart(2, '0');
  30. const seconds = date.getSeconds().toString().padStart(2, '0');
  31. return `${hours}:${minutes}:${seconds}`;
  32. }
  33.  
  34. // Function to calculate the relative time
  35. function getRelativeTime(datetime) {
  36. const now = new Date();
  37. const date = new Date(datetime);
  38. const diff = now - date;
  39.  
  40. const seconds = Math.floor(diff / 1000);
  41. const minutes = Math.floor(seconds / 60);
  42. const hours = Math.floor(minutes / 60);
  43. const days = Math.floor(hours / 24);
  44. const weeks = Math.floor(days / 7);
  45. const months = Math.floor(days / 30);
  46. const years = Math.floor(days / 365);
  47.  
  48. if (seconds < 60) {
  49. return `${seconds} second${seconds !== 1 ? 's' : ''} ago`;
  50. } else if (minutes < 60) {
  51. return `${minutes} minute${minutes !== 1 ? 's' : ''} ago`;
  52. } else if (hours < 24) {
  53. return `${hours} hour${hours !== 1 ? 's' : ''} ago`;
  54. } else if (days < 7) {
  55. return `${days} day${days !== 1 ? 's' : ''} ago`;
  56. } else if (weeks < 4) {
  57. return `${weeks} week${weeks !== 1 ? 's' : ''} ago`;
  58. } else if (months < 12) {
  59. return `${months} month${months !== 1 ? 's' : ''} ago`;
  60. } else {
  61. return `${years} year${years !== 1 ? 's' : ''} ago`;
  62. }
  63. }
  64.  
  65. // Function to detect if the user prefers 24-hour format
  66. function prefers24HourFormat() {
  67. const testDate = new Date(Date.UTC(2020, 0, 1, 13, 0, 0));
  68. const testDateString = testDate.toLocaleTimeString([], { hour: '2-digit' });
  69. return !testDateString.match(/AM|PM/i);
  70. }
  71.  
  72. // Function to update timestamps
  73. function updateTimestamps() {
  74. const timeElements = document.querySelectorAll('time');
  75. const use24HourFormat = prefers24HourFormat();
  76.  
  77. timeElements.forEach(timeElement => {
  78. const datetime = timeElement.getAttribute('datetime');
  79. if (datetime) {
  80. const originalLabel = timeElement.getAttribute('aria-label');
  81. const formattedTime = use24HourFormat
  82. ? formatTimestampWithSeconds24Hour(datetime)
  83. : formatTimestampWithSeconds12Hour(datetime);
  84. const relativeTime = getRelativeTime(datetime);
  85.  
  86. if (timeElement.parentElement.classList.contains('timestampVisibleOnHover_f9f2ca')) {
  87. // For hover timestamps, only show time without relative time
  88. timeElement.textContent = formattedTime;
  89. timeElement.setAttribute('aria-label', formattedTime);
  90. } else {
  91. // For normal timestamps, preserve the original format and add relative time
  92. if (!originalLabel.includes(formattedTime)) {
  93. timeElement.textContent = `${originalLabel.replace(/(\d+:\d+(:\d+)?\s*[APM]{2})/, formattedTime)} (${relativeTime})`;
  94. timeElement.setAttribute('aria-label', `${originalLabel.replace(/(\d+:\d+(:\d+)?\s*[APM]{2})/, formattedTime)} (${relativeTime})`);
  95. } else {
  96. // Update only the relative time
  97. const baseLabel = originalLabel.split(' (')[0];
  98. timeElement.textContent = `${baseLabel} (${relativeTime})`;
  99. timeElement.setAttribute('aria-label', `${baseLabel} (${relativeTime})`);
  100. }
  101. }
  102. }
  103. });
  104. }
  105.  
  106. // Observer to monitor DOM changes
  107. const observer = new MutationObserver(mutations => {
  108. for (const mutation of mutations) {
  109. if (mutation.type === 'childList' && mutation.addedNodes.length) {
  110. mutation.addedNodes.forEach(node => {
  111. if (node.nodeType === Node.ELEMENT_NODE) {
  112. const timeElements = node.querySelectorAll('time');
  113. timeElements.forEach(timeElement => {
  114. const datetime = timeElement.getAttribute('datetime');
  115. const originalLabel = timeElement.getAttribute('aria-label');
  116. const use24HourFormat = prefers24HourFormat();
  117.  
  118. if (datetime && originalLabel) {
  119. const formattedTime = use24HourFormat
  120. ? formatTimestampWithSeconds24Hour(datetime)
  121. : formatTimestampWithSeconds12Hour(datetime);
  122. const relativeTime = getRelativeTime(datetime);
  123.  
  124. if (timeElement.parentElement.classList.contains('timestampVisibleOnHover_f9f2ca')) {
  125. // For hover timestamps, only show time without relative time
  126. timeElement.textContent = formattedTime;
  127. timeElement.setAttribute('aria-label', formattedTime);
  128. } else {
  129. // For normal timestamps, preserve the original format and add relative time
  130. if (!originalLabel.includes(formattedTime)) {
  131. timeElement.textContent = `${originalLabel.replace(/(\d+:\d+(:\d+)?\s*[APM]{2})/, formattedTime)} (${relativeTime})`;
  132. timeElement.setAttribute('aria-label', `${originalLabel.replace(/(\d+:\d+(:\d+)?\s*[APM]{2})/, formattedTime)} (${relativeTime})`);
  133. } else {
  134. // Update only the relative time
  135. const baseLabel = originalLabel.split(' (')[0];
  136. timeElement.textContent = `${baseLabel} (${relativeTime})`;
  137. timeElement.setAttribute('aria-label', `${baseLabel} (${relativeTime})`);
  138. }
  139. }
  140. }
  141. });
  142. }
  143. });
  144. }
  145. }
  146. });
  147.  
  148. // Start observing the body for changes
  149. observer.observe(document.body, { childList: true, subtree: true });
  150.  
  151. // Refresh relative times every second
  152. setInterval(updateTimestamps, 1000);
  153.  
  154. // Initial timestamp update
  155. updateTimestamps();
  156.  
  157. })();