起因
后端接口返回的时间数据,是一个不带时区的 UTC 字符串。大概长这样:
2023-11-08T08:48:39
翻译到中国时区,就是
2023-11-08 16:48:39
我查找资料后发现,如果想让 new Date()
或 dayjs
默认解析并转换到当前时区,需要在此字符串的末尾加上一个 Z
代表它是 UTC+0
时区,这样前端就能直接识别出服务器返回的时间与对应的时区。
如果是一个带时区的时间,它应该是
2023-11-08T08:48:39Z(ISO 8601 规范,MDN 的推荐)
2023-11-08T08:48:39+0000(前端也能解析)
这两种日期格式交给 new Date() 都是可以直接解析的
MDN 对此的备注:
当用
Date
构造函数(和Date.parse
,它们是等价的)解析日期字符串时,一定要确保输入符合 ISO 8601 格式(YYYY-MM-DDTHH:mm:ss.ssZ
),其他格式的解析行为是实现定义的,可能无法在所有浏览器上运行。对 RFC 2822 格式字符串的支持只是惯例。如果要适应许多不同的格式,库可以提供帮助。仅有日期的字符串(例如
"1970-01-01"
)被视为 UTC,而日期时间的字符串(例如"1970-01-01T12:00"
)被视为本地时间。因此,我们也建议你确保这两种类型的输入格式是一致的。
但后端说这就是一个“UTC 时区”的时间,让我用 UTC 的方式解析,使用 dayjs
可以做到(dayjs.utc()
),但需引入对应的 UTC 插件。
对于这个字符串本身,我认为服务端能返回时区是最优解,因为其他项目之前也是这么做的,和客户端对接就没有任何沟通上的成本。
由于这个后端对接的不仅仅是一个 Web 前端,还对接了 iOS App 端,我询问了 App 端的实现过程,则和上面的情况类似,还说这是之前定下的“约定”。
说白了就是后端不返回时区的情况下,你都按照 UTC+0
的方式去解析这个时间字符串。
可我并不知道有这样的约定,我和其他前端对了下,发现他们也并不知道有这样的“约定”,甚至也有直接用 new Date()
解析的。也就是说这个时间字符串的问题在其他项目中也会是一个新 Bug。
后端把 JS 可以处理的方法甩过来之后,搞得我当即气急败坏。仿佛就是我做错了一样,这个问题难道后端就不背锅了么?
分析
考虑到我们团队的前端人数较多,App 开发就只有 2 人,如果要把这个“约定”告诉所有可能参与到项目维护的人来说是不现实的,且容易被疏忽,这不就是埋坑行为么。明明有个很好的官方规范在那,都是人家长期实践过的结果,为什么要自作主张搞一个额外的“约定”出来,增加沟通成本呢?
但现在项目已经完成到了这个程度,这个“错误”也一并存在了许久,就像 Referer
是一个错别字,Referrer
才是正确的一样,一个错误一旦影响程度面大了,后面就只能将错就错了。
如果让后端修改这个时间字符串的格式,他说除了调整当前项目,还需要将相关的几个后端项目一并修改。如果后端不修改,前端目前做好的项目恐怕也需要排查修改一遍,将来不排除还会存在前面提到的“埋坑”问题。
就算后端改了,前端又涉及到 App 端和 Web 端,还需要确认修改是否存在兼容性的问题才行。
前端这边展示过时间的位置确认都是错误的时区,理论上不需要做额外修改。就算按照 UTC 处理,也不存在这个问题:
dayjs.utc("2023-11-08T08:48:39”).unix()
// 169943319
dayjs.utc("2023-11-08T08:48:39Z”).unix()
// 169943319
就是不确定 App 端如果将一个「没带时区」的字符串变成「带时区」的字符串,是否又会变成一个“新的错误”。如果 App 端也是相同的结果,我认为后端应该把这个时间字符串更改为标准的 ISO 8601
规范,在将来的项目维护总是利大于弊的。
作为围观了这样一场风波的你,对此又如何选择呢。
已有 6 条评论
哈哈哈这就是有时多人协作带来的烦恼,前端和后端都认为对方可以解决,而自己懒得修改。这个时候就需要团队里的负责人或者一个强势的成员掷地有声毫不妥协的向所有成员定下规范,也就是俗话说的“主心骨”、“话事人”,不然矛盾还会继续存在,也会发生其他矛盾
有没有什么公共函数同时处理不同格式呢?如果有就好了。根据前端后端在返回它们的需求。当然我想当然了。
@叶开 如果不罗列或备注出来,其实大多数项目维护人员是不会知道有什么对应新增的公共函数的,最简单的办法还是消除额外的认知,一般标准怎么处理就怎么处理
我习惯用数字存,再转换成字符串
@ccbbp 确实是这样子,Unix 时间戳通用性很好,缺点就是光看数据本身的可读性不太行
就是一开始没订好正确的规范,后面就将错就错了,很多事情都是先上一个临时方案,然后就不再有机会改正。