Blog / WordPress/ Complete Implementation of Relative Post Time Display in WordPress (e.g., "Days Ago")

Complete Implementation of Relative Post Time Display in WordPress (e.g., "Days Ago")

WordPress 文章发布时间显示为相对时间(如“几天前”)的完整实现

Tired of WordPress's default static post date format? Want your site to display relative times like "a few minutes ago," "a few hours ago," or "a few days ago" to enhance the timeliness and interactivity of your content? This article provides a complete, standard, and easy-to-integrate solution.

Implementation Principle

WordPress outputs post publication times via functions like the_time() or get_the_date(). We can use WordPress's filter mechanism to process the time before output, calculate the difference between the publication time and the current time, and convert it into an easy-to-understand relative time format.

Core Function Code

Add the following code to the end of your child theme's functions.php file, or add it via a "Code Snippets" plugin.

/**
 * Convert post publication time to relative time format (e.g., "3 minutes ago").
 *
 * @param string $time The original time string.
 * @return string The converted relative time or original date.
 */
function wp_custom_relative_time($time) {
    // Process only within the main loop for posts/pages
    if (!is_single() && !is_page() && !in_the_loop()) {
        return $time;
    }

    $post_time = get_post_time('U', true); // Get post Unix timestamp
    $current_time = current_time('timestamp'); // Get current Unix timestamp
    $time_diff = $current_time - $post_time; // Calculate difference in seconds

    // If post time is in the future (e.g., scheduled), return original time
    if ($time_diff < 0) {
        return $time;
    }

    // Define time units in seconds
    $minute = 60;
    $hour = 60 * $minute;
    $day = 24 * $hour;
    $week = 7 * $day;
    $month = 30 * $day; // Approximation
    $year = 365 * $day; // Approximation

    // Return relative time string based on difference
    if ($time_diff < $minute) {
        return __('Just now', 'your-text-domain');
    } elseif ($time_diff < $hour) {
        $mins = round($time_diff / $minute);
        return sprintf(_n('%s minute ago', '%s minutes ago', $mins, 'your-text-domain'), $mins);
    } elseif ($time_diff < $day) {
        $hours = round($time_diff / $hour);
        return sprintf(_n('%s hour ago', '%s hours ago', $hours, 'your-text-domain'), $hours);
    } elseif ($time_diff < $week) {
        $days = round($time_diff / $day);
        return sprintf(_n('%s day ago', '%s days ago', $days, 'your-text-domain'), $days);
    } elseif ($time_diff < $month) {
        $weeks = round($time_diff / $week);
        return sprintf(_n('%s week ago', '%s weeks ago', $weeks, 'your-text-domain'), $weeks);
    } elseif ($time_diff < $year) {
        $months = round($time_diff / $month);
        return sprintf(_n('%s month ago', '%s months ago', $months, 'your-text-domain'), $months);
    } else {
        // Over a year, return original formatted date for consistency
        return get_the_date(get_option('date_format'));
    }
}
// Apply filter to the_time and get_the_date
add_filter('the_time', 'wp_custom_relative_time');
add_filter('get_the_date', 'wp_custom_relative_time');

Code Explanation & Optimizations

  • Robustness Check: Includes a check for being within the main loop to avoid affecting date displays elsewhere (e.g., widgets).
  • Complete Time Range: Covers the full range from "just now" to "years ago," adding "week" and "month" units for more natural expression.
  • Internationalization Support: Uses __(), _n(), and sprintf() with a specified text domain ('your-text-domain') for easy translation. Replace with your theme's actual text domain.
  • Future Time Handling: Handles edge cases where scheduled posts have a future publication time.
  • Dual Filter Application: Filters both the_time and get_the_date to ensure it works regardless of which function is called.

Usage

After adding the code, no further action is needed. All post times output via the_time() or get_the_date() in your theme will automatically convert to relative time format.

For example, in your theme's single.php or content.php template file, you might have code like:

<?php the_time('F j, Y'); ?>

After adding our filter, it will no longer show "April 15, 2023" but instead display "2 days ago" or "1 month ago" based on the current time.

Advanced Customization & Notes

1. Control Display Range

If you want relative times only within a specific period (e.g., 30 days), modify the final else condition. For example, change the "one year" check to "30 days":

// ... previous conditions ...
} elseif ($time_diff < (30 * $day)) { // Within 30 days
    $days = round($time_diff / $day);
    return sprintf(_n('%s day ago', '%s days ago', $days, 'your-text-domain'), $days);
} else {
    // Over 30 days, return standard date format
    return get_the_date(get_option('date_format'));
}

2. Exclude Specific Pages

To disable the effect on the homepage or archive pages, use conditional tags:

function wp_custom_relative_time_conditional($time) {
    // Do not apply on homepage, archives, or search
    if (is_home() || is_archive() || is_search()) {
        return $time;
    }
    // Otherwise, call the original relative time function
    return wp_custom_relative_time($time);
}
// Replace the original filters
remove_filter('the_time', 'wp_custom_relative_time');
remove_filter('get_the_date', 'wp_custom_relative_time');
add_filter('the_time', 'wp_custom_relative_time_conditional');
add_filter('get_the_date', 'wp_custom_relative_time_conditional');

3. Caching Plugin Considerations

If you use static caching plugins (e.g., W3 Total Cache, WP Super Cache), relative times may be cached and fixed. Solutions:

  • Use the caching plugin's "exclusion rules" to not cache the date-containing section.
  • Consider a JavaScript client-side solution, though this may reduce SEO friendliness.

Summary

Following these steps, you can easily add a friendly, dynamic relative time display to your WordPress site. This improves user experience and makes content feel fresher. Remember to back up your theme files before editing, or use a child theme.

Post a Comment

Your email will not be published. Required fields are marked with *.