Files
Neo-ZQYY/docs/miniprogram-dev/design-system/DATETIME-DISPLAY-STANDARD.md

219 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 日期时间展示规范(小程序前端)
> **文档编号**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
```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` 统一工具
---
## 八、关联文档
- [VI 设计规范](./VI-DESIGN-SYSTEM.md)
- [组件库规范](../components/)
- `apps/miniprogram/miniprogram/utils/time.js`(工具函数实现位置)