6.7 KiB
6.7 KiB
日期时间展示规范(小程序前端)
文档编号:DS-DATETIME-001
版本:v1.1.0
适用范围:NeoZQYY 小程序所有前端页面
最后更新:2026-03-18
一、设计原则
- 就近优先:越近的时间用越自然的语言表达,减少认知负担。
- 精度递减:随时间距离增大,展示精度逐步降低(秒 → 分 → 时 → 天 → 日期)。
- 一致性:全端统一规则,禁止页面间自行实现差异逻辑。
- 可读性优先:格式选择以用户直觉理解为准,而非技术精确。
二、展示规则总表
| 时间距当前的范围 | 展示格式 | 示例 |
|---|---|---|
| 0 秒 ~ 119 秒(不足 2 分钟) | 刚刚 |
刚刚 |
| 2 分钟 ~ 59 分钟 | N分钟前 |
2分钟前 / 59分钟前 |
| 1 小时 ~ 23 小时 59 分 | N小时前 |
1小时前 / 23小时前 |
| 24 小时 ~ 71 小时 59 分(1天~3天内) | N天前 |
1天前 / 3天前 |
| 超过 72 小时(3天前以上) | YYYY-MM-DD |
2026-03-10 |
注:所有时间差计算以服务端返回的 UTC 时间戳为基准,前端根据设备本地时区渲染,不得使用客户端本地时间作为「当前时间」基准。
三、逐级规则详解
3.1 刚刚(0 ~ 119 秒)
- 触发条件:
now - timestamp < 120 秒 - 展示文案:
刚刚 - 说明:2 分钟内的时间差对用户无感知意义,统一收敛为「刚刚」,不展示具体秒数或分钟数。
示例:发布于 5 秒前 → 刚刚
发布于 90 秒前 → 刚刚
发布于 119 秒前 → 刚刚
3.2 N 分钟前(2 ~ 59 分钟)
- 触发条件:
120 秒 ≤ now - timestamp < 3600 秒 - 展示格式:
Math.floor(diff / 60) + '分钟前' - 最小值:2分钟前
- 最大值:59分钟前
示例:
diff = 120s → 2分钟前
diff = 3540s → 59分钟前
不得 展示「1分钟前」(119 秒内均为「刚刚」);不得 展示「60分钟前」,3600 秒起跳进入「小时」维度。
3.3 N 小时前(1 ~ 23 小时)
- 触发条件:
3600 秒 ≤ now - timestamp < 86400 秒 - 展示格式:
Math.floor(diff / 3600) + '小时前' - 最小值:1小时前
- 最大值:23小时前
示例:
diff = 3600s → 1小时前
diff = 82800s → 23小时前
不得 展示「24小时前」,86400 秒起跳进入「天」维度。
3.4 N 天前(1 ~ 3 天)
- 触发条件:
86400 秒 ≤ now - timestamp < 259200 秒(即 1 天 ~ 不足 72 小时) - 展示格式:
Math.floor(diff / 86400) + '天前' - 最小值:1天前
- 最大值:3天前
示例:
diff = 86400s → 1天前
diff = 259199s → 3天前
临界说明:72小时(259200秒)整数点,即 diff ≥ 259200 秒,切换为日期格式。
3.5 日期展示(超过 3 天)
- 触发条件:
now - timestamp ≥ 259200 秒(≥ 72 小时) - 展示格式:
- 同年:
MM-DD(省略年份,如03-10) - 跨年:
YYYY-MM-DD(保留年份,如2025-08-21)
- 同年:
- 分隔符:使用连字符
-,不使用斜杠/或中文「年月日」 - 不展示时分秒:日期维度下不展示具体时刻。
示例(当前日期 2026-03-18):
时间戳 2026-03-10 → 03-10
时间戳 2025-08-21 → 2025-08-21(跨年展示完整年份)
四、判断流程图
输入:服务端时间戳 timestamp
│
▼
diff = now - timestamp(单位:秒)
│
┌─────┴───────┐
│ diff < 120 │──► 刚刚
└─────┬───────┘
│
┌─────┴──────────┐
│ diff < 3600 │──► N分钟前(N = floor(diff/60),2≤N≤59)
└─────┬──────────┘
│
┌─────┴──────────┐
│ diff < 86400 │──► N小时前(N = floor(diff/3600),1≤N≤23)
└─────┬──────────┘
│
┌─────┴──────────┐
│ diff < 259200 │──► N天前(N = floor(diff/86400),1≤N≤3)
└─────┬──────────┘
│
▼
日期格式(同年MM-DD / 跨年YYYY-MM-DD)
五、前端实现参考(JavaScript)
/**
* 格式化时间展示
* @param {number} timestamp - 服务端返回的 Unix 时间戳(毫秒)
* @returns {string} 格式化后的时间文案
*/
function formatRelativeTime(timestamp) {
const now = Date.now();
const diff = Math.floor((now - timestamp) / 1000); // 转换为秒
if (diff < 120) {
return '刚刚';
}
if (diff < 3600) {
return `${Math.floor(diff / 60)}分钟前`;
}
if (diff < 86400) {
return `${Math.floor(diff / 3600)}小时前`;
}
if (diff < 259200) { // 72小时 = 3天
return `${Math.floor(diff / 86400)}天前`;
}
// 超过3天,展示日期
const date = new Date(timestamp);
const nowDate = new Date(now);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
if (year === nowDate.getFullYear()) {
return `${month}-${day}`; // 同年省略年份
}
return `${year}-${month}-${day}`; // 跨年显示完整年份
}
微信小程序说明:可直接将此函数挂载到
utils/time.js,在 WXML 中通过wxs模块或Page.data绑定使用。
六、边界与特殊情况处理
| 场景 | 处理方式 |
|---|---|
timestamp 为空 / undefined |
展示 --,不报错 |
timestamp 为未来时间(服务端时钟偏差) |
统一展示 刚刚(diff < 0 时按 0 处理) |
| 用户设备时区异常 | 以服务端返回的格式化日期字段(fallback)为准 |
| 时间戳单位(秒 vs 毫秒) | 统一由服务端约定为毫秒,前端不做猜测 |
七、禁止事项
- ❌ 禁止展示「1分钟前」「60分钟前」「24小时前」「0分钟前」等临界歧义文案(2分钟内统一展示「刚刚」)
- ❌ 禁止在「天」维度之后继续展示相对文案(如「7天前」「30天前」)
- ❌ 禁止使用中文「年月日」格式(如「2026年3月10日」),统一使用
-分隔符 - ❌ 禁止在超3天后展示时分秒
- ❌ 禁止各页面自行定义时间格式化函数,必须引用
utils/time.js统一工具