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

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

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

厌倦了 WordPress 默认的静态文章发布时间格式吗?想让你的网站显示“几分钟前”、“几小时前”或“几天前”这样的相对时间,以增强内容的时效感和互动性吗?本文将为你提供一个完整、标准且易于集成的解决方案。

实现原理

WordPress 通过 the_time()get_the_date() 等函数输出文章发布时间。我们可以通过 WordPress 的过滤器(Filter)机制,在时间输出前对其进行处理,计算发布时间与当前时间的差值,并将其转换为易于理解的相对时间格式。

核心功能代码

将以下代码添加到你的子主题的 functions.php 文件末尾,或通过“代码片段”插件添加。

/**
 * 将文章发布时间转换为相对时间格式(如“3分钟前”)
 *
 * @param string $time 原始时间字符串。
 * @return string 转换后的相对时间或原始日期。
 */
function wp_custom_relative_time($time) {
    // 仅在主循环中处理文章发布时间
    if (!is_single() && !is_page() && !in_the_loop()) {
        return $time;
    }

    $post_time = get_post_time('U', true); // 获取文章发布时间的 Unix 时间戳
    $current_time = current_time('timestamp'); // 获取当前时间的 Unix 时间戳
    $time_diff = $current_time - $post_time; // 计算时间差(秒)

    // 如果文章发布时间在未来(可能由于定时发布),则返回原始时间
    if ($time_diff < 0) {
        return $time;
    }

    // 定义时间单位(秒)
    $minute = 60;
    $hour = 60 * $minute;
    $day = 24 * $hour;
    $week = 7 * $day;
    $month = 30 * $day; // 近似值
    $year = 365 * $day; // 近似值

    // 根据时间差返回相应的相对时间字符串
    if ($time_diff < $minute) {
        return __('刚刚', 'your-text-domain');
    } elseif ($time_diff < $hour) {
        $mins = round($time_diff / $minute);
        return sprintf(_n('%s分钟前', '%s分钟前', $mins, 'your-text-domain'), $mins);
    } elseif ($time_diff < $day) {
        $hours = round($time_diff / $hour);
        return sprintf(_n('%s小时前', '%s小时前', $hours, 'your-text-domain'), $hours);
    } elseif ($time_diff < $week) {
        $days = round($time_diff / $day);
        return sprintf(_n('%s天前', '%s天前', $days, 'your-text-domain'), $days);
    } elseif ($time_diff < $month) {
        $weeks = round($time_diff / $week);
        return sprintf(_n('%s周前', '%s周前', $weeks, 'your-text-domain'), $weeks);
    } elseif ($time_diff < $year) {
        $months = round($time_diff / $month);
        return sprintf(_n('%s个月前', '%s个月前', $months, 'your-text-domain'), $months);
    } else {
        // 超过一年,返回原始格式化日期,保持一致性
        return get_the_date(get_option('date_format'));
    }
}
// 将过滤器应用到 the_time 和 get_the_date
add_filter('the_time', 'wp_custom_relative_time');
add_filter('get_the_date', 'wp_custom_relative_time');

代码说明与优化

  • 健壮性检查:代码增加了对是否在主循环内的判断,避免影响其他地方的日期显示(如小工具)。
  • 时间范围更完整:覆盖了从“刚刚”到“几年前”的完整范围,并增加了“周”和“月”的单位,使表达更自然。
  • 国际化支持:使用 __(), _n()sprintf() 函数,并指定了文本域(‘your-text-domain’),便于主题或插件翻译。请将其替换为你主题的实际文本域。
  • 未来时间处理:处理了定时发布文章导致发布时间在未来时的边界情况。
  • 双过滤器应用:同时过滤 the_timeget_the_date,确保通过不同函数调用时间都能生效。

使用方法

添加上述代码后,无需额外操作。你的主题中所有通过 the_time()get_the_date() 输出的发布时间,将自动转换为相对时间格式。

例如,在主题的 single.phpcontent.php 模板文件中,通常会有如下代码:

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

添加我们的过滤器后,它将不再显示“April 15, 2023”,而是根据当前时间显示为“2天前”或“1个月前”。

高级自定义与注意事项

1. 控制显示范围

如果你希望仅在特定时间范围内(如30天内)显示相对时间,超过则显示绝对日期,可以修改代码最后的 else 分支条件。例如,将判断“一年”改为“30天”:

// ... 省略前面的判断 ...
} elseif ($time_diff < (30 * $day)) { // 30天内
    $days = round($time_diff / $day);
    return sprintf(_n('%s天前', '%s天前', $days, 'your-text-domain'), $days);
} else {
    // 超过30天,返回标准日期格式
    return get_the_date(get_option('date_format'));
}

2. 排除特定页面

如果你不想在首页或分类页面应用此效果,可以使用条件标签:

function wp_custom_relative_time_conditional($time) {
    // 不在首页、归档页应用此效果
    if (is_home() || is_archive() || is_search()) {
        return $time;
    }
    // 否则,调用原来的相对时间函数
    return wp_custom_relative_time($time);
}
// 替换原来的过滤器
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. 清除缓存插件的影响

如果你使用了静态缓存插件(如 W3 Total Cache, WP Super Cache),相对时间可能会被缓存并固定显示。解决方法有两种:

  • 通过缓存插件的“排除规则”设置,不缓存包含日期的部分。
  • 考虑使用 JavaScript 客户端方案来实现相对时间,但这会牺牲一些SEO友好性。

总结

通过以上步骤,你可以轻松地为你的 WordPress 网站添加友好且动态的相对时间显示功能。这不仅提升了用户体验,也让内容显得更加鲜活。记得在修改主题文件前做好备份,或优先使用子主题进行操作。

发表评论

您的邮箱不会公开。必填项已用 * 标注。