uni-app 中日期处理需统一解析逻辑,优先转时间戳再构造Date对象,避免iOS兼容问题;过滤器仅用于轻量转换,复杂逻辑放methods或工具函数;全局格式化推荐挂载到uni.$date而非修改原型;uni-dateformat组件threshold须用数组配置。

直接用过滤器或全局函数处理日期,在 uni-app 里不是不行,但容易埋坑——尤其是跨平台时 iOS 和 Android 对 Date 构造行为不一致,比如传入 "2026-04-21" 在 iOS 可能解析为 UTC 时间,导致显示错一天。别急着写 filters 或 methods,先看这几个关键点。
uni-app 过滤器(filters)里 new Date() 的兼容性陷阱
很多人在 filters 里直接写 new Date(date),结果在真机上出问题。核心原因是:iOS Safari 不支持 new Date("2026-04-21") 这种带短横线的字符串格式(只认 "2026/04/21" 或时间戳),而 H5 和 Android WebView 表现又不同。
- 传入字符串时,优先转成时间戳再构造:
const ts = typeof date === 'string' ? Date.parse(date.replace(/-/g, '/')) : date; - 永远显式判断类型:
if (!(date instanceof Date)) date = new Date(ts); - 避免在
filters中做复杂逻辑,它只适合轻量、无副作用的转换;含“今天”“刚刚”这类相对时间的逻辑,放methods或工具函数里更可控
全局函数比 filters 更可靠,但得挂对地方
把格式化函数挂到 Vue.prototype 或 uni.$date 是常见做法,但要注意初始化时机和作用域。例如在 main.js 里扩展 Date.prototype.format 看似方便,但会污染原生原型,且 TypeScript 类型提示不友好。
- 推荐方式:封装为独立模块
utils/date.js,导出纯函数formatDate(date, fmt),按需引入 - 若要用全局访问,挂到
uni.$date = { formatDate, fromNow },而不是改Date.prototype - 注意
uni.$date在非 Vue 实例上下文(如 Vuex action、API 请求拦截器)中不可用,此时必须 import 模块
uni-dateformat 组件的 threshold 容易被误用
组件默认开启人性化显示(“刚刚”“5分钟前”),但它的 threshold 属性是数组,不是布尔值。很多人写成 :threshold="false" 或 :threshold="0",结果没效果。
- 禁用人性化显示,必须写成:
:threshold="[0, 0]" - 想让“1小时内”都显示为“xx分钟前”,但“1小时外”走自定义格式,就设为:
:threshold="[0, 3600000]" -
threshold第一个值是“刚刚”的上限(毫秒),第二个是“xx分钟前”的上限;超出第二项才 fallback 到format字符串 - 组件内部用的是
Date.now(),不依赖本地时区设置,这点比手写逻辑更稳
真正难的不是写一个 formatDate 函数,而是统一所有时间输入源的解析逻辑——接口返回的时间戳、字符串、ISO 格式、甚至后端乱写的 "2026.04.21" 都得兜住。建议在请求拦截器里就做一次标准化归一(转成毫秒或 Date 对象),后面所有展示层才不会反复踩坑。











