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.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Discord Timestamp with Seconds
// @namespace    http://tampermonkey.net/
// @version      3.4
// @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.
// @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)
// @match        https://discord.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Function to format the timestamp with seconds in 12-hour format
    function formatTimestampWithSeconds12Hour(datetime) {
        const date = new Date(datetime);
        const hours = date.getHours() % 12 || 12;
        const minutes = date.getMinutes().toString().padStart(2, '0');
        const seconds = date.getSeconds().toString().padStart(2, '0');
        const ampm = date.getHours() >= 12 ? 'PM' : 'AM';
        return `${hours}:${minutes}:${seconds} ${ampm}`;
    }

    // Function to format the timestamp with seconds in 24-hour format
    function formatTimestampWithSeconds24Hour(datetime) {
        const date = new Date(datetime);
        const hours = date.getHours().toString().padStart(2, '0');
        const minutes = date.getMinutes().toString().padStart(2, '0');
        const seconds = date.getSeconds().toString().padStart(2, '0');
        return `${hours}:${minutes}:${seconds}`;
    }

    // Function to calculate the relative time
    function getRelativeTime(datetime) {
        const now = new Date();
        const date = new Date(datetime);
        const diff = now - date;

        const seconds = Math.floor(diff / 1000);
        const minutes = Math.floor(seconds / 60);
        const hours = Math.floor(minutes / 60);
        const days = Math.floor(hours / 24);
        const weeks = Math.floor(days / 7);
        const months = Math.floor(days / 30);
        const years = Math.floor(days / 365);

        if (seconds < 60) {
            return `${seconds} second${seconds !== 1 ? 's' : ''} ago`;
        } else if (minutes < 60) {
            return `${minutes} minute${minutes !== 1 ? 's' : ''} ago`;
        } else if (hours < 24) {
            return `${hours} hour${hours !== 1 ? 's' : ''} ago`;
        } else if (days < 7) {
            return `${days} day${days !== 1 ? 's' : ''} ago`;
        } else if (weeks < 4) {
            return `${weeks} week${weeks !== 1 ? 's' : ''} ago`;
        } else if (months < 12) {
            return `${months} month${months !== 1 ? 's' : ''} ago`;
        } else {
            return `${years} year${years !== 1 ? 's' : ''} ago`;
        }
    }

    // Function to detect if the user prefers 24-hour format
    function prefers24HourFormat() {
        const testDate = new Date(Date.UTC(2020, 0, 1, 13, 0, 0));
        const testDateString = testDate.toLocaleTimeString([], { hour: '2-digit' });
        return !testDateString.match(/AM|PM/i);
    }

    // Function to update timestamps
    function updateTimestamps() {
        const timeElements = document.querySelectorAll('time');
        const use24HourFormat = prefers24HourFormat();

        timeElements.forEach(timeElement => {
            const datetime = timeElement.getAttribute('datetime');
            if (datetime) {
                const originalLabel = timeElement.getAttribute('aria-label');
                const formattedTime = use24HourFormat
                    ? formatTimestampWithSeconds24Hour(datetime)
                    : formatTimestampWithSeconds12Hour(datetime);
                const relativeTime = getRelativeTime(datetime);

                if (timeElement.parentElement.classList.contains('timestampVisibleOnHover_f9f2ca')) {
                    // For hover timestamps, only show time without relative time
                    timeElement.textContent = formattedTime;
                    timeElement.setAttribute('aria-label', formattedTime);
                } else {
                    // For normal timestamps, preserve the original format and add relative time
                    if (!originalLabel.includes(formattedTime)) {
                        timeElement.textContent = `${originalLabel.replace(/(\d+:\d+(:\d+)?\s*[APM]{2})/, formattedTime)} (${relativeTime})`;
                        timeElement.setAttribute('aria-label', `${originalLabel.replace(/(\d+:\d+(:\d+)?\s*[APM]{2})/, formattedTime)} (${relativeTime})`);
                    } else {
                        // Update only the relative time
                        const baseLabel = originalLabel.split(' (')[0];
                        timeElement.textContent = `${baseLabel} (${relativeTime})`;
                        timeElement.setAttribute('aria-label', `${baseLabel} (${relativeTime})`);
                    }
                }
            }
        });
    }

    // Observer to monitor DOM changes
    const observer = new MutationObserver(mutations => {
        for (const mutation of mutations) {
            if (mutation.type === 'childList' && mutation.addedNodes.length) {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        const timeElements = node.querySelectorAll('time');
                        timeElements.forEach(timeElement => {
                            const datetime = timeElement.getAttribute('datetime');
                            const originalLabel = timeElement.getAttribute('aria-label');
                            const use24HourFormat = prefers24HourFormat();

                            if (datetime && originalLabel) {
                                const formattedTime = use24HourFormat
                                    ? formatTimestampWithSeconds24Hour(datetime)
                                    : formatTimestampWithSeconds12Hour(datetime);
                                const relativeTime = getRelativeTime(datetime);

                                if (timeElement.parentElement.classList.contains('timestampVisibleOnHover_f9f2ca')) {
                                    // For hover timestamps, only show time without relative time
                                    timeElement.textContent = formattedTime;
                                    timeElement.setAttribute('aria-label', formattedTime);
                                } else {
                                    // For normal timestamps, preserve the original format and add relative time
                                    if (!originalLabel.includes(formattedTime)) {
                                        timeElement.textContent = `${originalLabel.replace(/(\d+:\d+(:\d+)?\s*[APM]{2})/, formattedTime)} (${relativeTime})`;
                                        timeElement.setAttribute('aria-label', `${originalLabel.replace(/(\d+:\d+(:\d+)?\s*[APM]{2})/, formattedTime)} (${relativeTime})`);
                                    } else {
                                        // Update only the relative time
                                        const baseLabel = originalLabel.split(' (')[0];
                                        timeElement.textContent = `${baseLabel} (${relativeTime})`;
                                        timeElement.setAttribute('aria-label', `${baseLabel} (${relativeTime})`);
                                    }
                                }
                            }
                        });
                    }
                });
            }
        }
    });

    // Start observing the body for changes
    observer.observe(document.body, { childList: true, subtree: true });

    // Refresh relative times every second
    setInterval(updateTimestamps, 1000);

    // Initial timestamp update
    updateTimestamps();

})();