uni-app 时间格式化需统一处理:时间戳用 new Date(timestamp) 安全,但后续方法需注意时区;年月日时分秒必须两位补零;字符串时间需标准化再解析;推荐封装纯函数挂载到 uni.$date,避免修改 Date.prototype;uni-dateformat 的 threshold 必须传毫秒数组。
直接用 new date(timestamp) 格式化时间戳在 uni-app 里最常见,但真机上容易出错——尤其 ios 微信小程序和 h5 对 date 构造行为不一致,传入时间戳本身虽安全,但后续调用 getyear()、tolocalestring() 等方法时,时区和本地化表现可能漂移。
时间戳转「年-月-日 时:分:秒」必须显式补零
很多人写 date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate(),结果出现 2026-5-30 这种非标准格式。uni-app 渲染层对空格、短横线敏感,后端或组件(如 uni-dateformat)可能解析失败。
- 月份、日期、小时、分钟、秒都必须两位补零,推荐用
String(num).padStart(2, '0')或('0' + num).slice(-2) - 不要依赖
date.toISOString().slice(0, 19).replace('T', ' '):iOS 下可能返回 UTC 时间,比本地早 8 小时 - 如果只显示日期(如列表项),用
yyyy-MM-dd格式;含时间则固定用yyyy-MM-dd HH:mm:ss,HH表示 24 小时制,避免 AM/PM 混乱
过滤器(filters)里处理时间戳要绕开字符串解析陷阱
虽然文档说 filters 支持 {{ timestamp | formatDate }},但很多开发者误把后端返回的字符串时间(如 "2026-04-21")也塞进同一个过滤器,结果在 iOS 上 new Date("2026-04-21") 直接返回 Invalid Date。
- 过滤器函数第一行必须判断类型:
if (typeof date === 'string' && !/^\d+$/.test(date)) { date = date.replace(/-/g, '/'); } - 时间戳是数字,直接
new Date(date);字符串先标准化再构造,别混用逻辑 - 微信小程序端
filters支持不完整,建议优先用methods或计算属性,更可控
全局格式化函数挂载到 uni.$date 而不是 Date.prototype
有人在 main.js 里写 Date.prototype.format = function(fmt) {...},看似方便,但 TypeScript 类型无法识别,且一旦其他库也改写 Date.prototype,就可能冲突或覆盖。
- 新建
utils/date.js,导出纯函数:export function formatDate(date, fmt = 'yyyy-MM-dd HH:mm:ss') - 在
main.js中挂载:uni.$date = { formatDate },组件内用uni.$date.formatDate(ts) - 注意:Vuex action、request 拦截器等非 Vue 实例上下文中,
uni.$date不可用,此时必须import { formatDate } from '@/utils/date'
uni-dateformat 组件的 threshold 必须传数组
想禁用“刚刚”“5分钟前”这类人性化提示,只显示固定格式,却写成 :threshold="false" 或 :threshold="0",结果毫无作用——因为它的 threshold 是毫秒数组,不是布尔值或数字。
- 完全关闭人性化显示:
:threshold="[0, 0]" - 只对 1 小时内做相对显示,超时走 format:
:threshold="[0, 3600000]" - 组件内部用
Date.now()计算差值,不依赖系统时区设置,这点比手写逻辑更稳
真正难的不是写对一个格式化函数,而是让同一套逻辑在微信小程序、App、H5 三端输出完全一致的时间字符串。iOS 的 Date 解析限制、Android WebView 的时区策略、H5 的 Intl 支持程度——这些细节不验证到真机,光看模拟器永远发现不了问题。











