织梦日期标签距离当前时间写法

"3 天前发布"、"剩余 5 天截止"、"2 年前更新"这类距离当前时间的时间差显示,比绝对时间更直观,用户体验更好。织梦的 pubdate 字段存的是时间戳,计算时间差只需用当前时间减去发布时间。本文给出几种典型写法。

一、时间差计算原理

当前时间戳:time()           如 1706899200
发布时间戳:pubdate          如 1706745600
时间差(秒):time() - pubdate=153600 秒
换算:
  153600 / 60=2560 分钟
  2560 / 60=42.6 小时
  42.6 / 24=1.78 天

所有"几天前"都是基于这个差值除以对应单位得到的。

二、写法一:runphp 直接计算

[field:pubdate runphp='yes']
  $diff=time() - @me;
  if($diff < 60) @me='刚刚';
  elseif($diff < 3600) @me=floor($diff/60).' 分钟前';
  elseif($diff < 86400) @me=floor($diff/3600).' 小时前';
  elseif($diff < 2592000) @me=floor($diff/86400).' 天前';
  elseif($diff < 31536000) @me=floor($diff/2592000).' 个月前';
  else @me=floor($diff/31536000).' 年前';
[/field:pubdate]

三、写法二:封装为自定义函数(推荐)

// /include/extend.func.php
function TimeAgo($time){
  $diff=time() - $time;
  if($diff < 0) return '未来时间';  // 时间戳大于当前
  if($diff < 60) return '刚刚';
  if($diff < 3600) return floor($diff/60).' 分钟前';
  if($diff < 86400) return floor($diff/3600).' 小时前';
  if($diff < 2592000) return floor($diff/86400).' 天前';
  if($diff < 31536000) return floor($diff/2592000).' 个月前';
  return floor($diff/31536000).' 年前';
}

模板调用:

[field:pubdate function="TimeAgo(@me)"/]
{dede:field.pubdate function="TimeAgo(@me)"/}

四、写法三:超过 N 天显示绝对时间

常见做法是"7 天内显示几天前,7 天后显示标准日期":

function SmartTime($time){
  $diff=time() - $time;
  if($diff < 86400*7){
    // 7 天内用友好时间
    if($diff < 60) return '刚刚';
    if($diff < 3600) return floor($diff/60).'分钟前';
    if($diff < 86400) return floor($diff/3600).'小时前';
    return floor($diff/86400).'天前';
  } else {
    // 7 天后用标准日期
    return MyDate('Y-m-d', $time);
  }
}

五、距离未来时间(倒计时)

活动页常用"距结束还剩 X 天":

// 自定义字段 endtime 存活动结束时间戳
[field:endtime runphp='yes']
  $diff=@me - time();
  if($diff <=0){
    @me='已结束';
  } elseif($diff < 86400){
    @me='剩 '.floor($diff/3600).' 小时';
  } else {
    @me='剩 '.floor($diff/86400).' 天';
  }
[/field:endtime]

精确到时分秒的倒计时

function Countdown($endtime){
  $diff=$endtime - time();
  if($diff <=0) return '已结束';
  $d=floor($diff/86400);
  $h=floor(($diff%86400)/3600);
  $m=floor(($diff%3600)/60);
  $s=$diff%60;
  return "{$d}天 {$h}时 {$m}分 {$s}秒";
}

六、典型应用场景

1. 列表页友好时间

{dede:arclist typeid='1' row='10'}
  <li>
    <span class="time">[field:pubdate function="TimeAgo(@me)"/]</span>
    <a href="[field:arcurl/]">[field:title/]</a>
  </li>
{/dede:arclist}

2. 内容页"最后更新"提示

<p class="update-info">
  本文最后更新于 {dede:field.pubdate function="SmartTime(@me)"/}
  ,请注意内容时效性。
</p>

3. 活动倒计时

<div class="countdown">
  距活动结束:{dede:field.endtime function="Countdown(@me)"/}
</div>

4. 新文章标识

[field:pubdate runphp='yes']
  $diff=time() - @me;
  if($diff < 86400*3){  // 3 天内
    @me='<span class="new-tag">NEW</span>';
  } else {
    @me='';
  }
[/field:pubdate]

七、时间差对照表

秒数天数显示
601 分钟刚刚
36001 小时X 分钟前
864001 天X 小时前
2592003 天X 天前
6048007 天X 天前 / 切换绝对时间
259200030 天X 个月前
31536000365 天X 年前

八、注意事项

静态页时间差会"冻结":静态 HTML 生成后,里面的"3 天前"就被写死成文本了,不会随时间推移变化。需要实时时间差必须用动态页或用 JS 计算。

JS 动态计算时间差:静态页用 JS 实现实时"几天前":

<span data-time="[field:pubdate/]" class="js-time">[field:pubdate function="MyDate('Y-m-d',@me)"/]</span>
<script>
document.querySelectorAll('.js-time').forEach(function(el){
  var t=parseInt(el.getAttribute('data-time')) * 1000;
  var diff=Date.now() - t;
  var txt;
  if(diff < 60000) txt='刚刚';
  else if(diff < 3600000) txt=Math.floor(diff/60000)+'分钟前';
  else if(diff < 86400000) txt=Math.floor(diff/3600000)+'小时前';
  else txt=Math.floor(diff/86400000)+'天前';
  el.innerText=txt;
});
</script>

时间戳为 0 的处理:某些文章 pubdate 为 0,TimeAgo 会输出"55 年前"。函数开头加判断:if($time==0) return '未知时间';

未来时间处理:采集或定时发布时,pubdate 可能大于当前时间,TimeAgo 会输出负数。函数开头加 if($diff < 0) return '即将发布';

九、应用建议

时间差显示能显著提升用户体验,但要注意静态与动态的差异。纯静态站点建议用 JS 动态计算时间差(保留 HTML 里的时间戳作为 data 属性),既不影响 SEO(搜索引擎抓到的是绝对时间),又能让用户看到实时"几天前"。把 TimeAgo、SmartTime、Countdown 三个函数固化进 extend.func.php,覆盖"过去时间、智能切换、未来倒计时"三种场景。SEO 与体验兼顾的最佳实践是:HTML 里同时输出绝对时间(time 标签)与时间戳(data 属性),JS 把时间戳转成友好显示,搜索引擎仍能读到准确的发布日期。