React Native修改设备时间后如何获取Firebase正确时间戳
问题背景
使用以下代码在Firestore中设置服务端时间戳时,能够写入正确的时间值:
firebase.firestore.FieldValue.serverTimestamp() // 写入Firestore的返回值 = {"seconds":1656487980,"nanoseconds":840000000} // 对应实际时间:June 29, 2022 7:33:00 AM
同一时段使用客户端本地时间API获取时间戳时,返回结果存在偏差:
Timestamp.fromDate(new Date()); // {"seconds":1656491580,"nanoseconds":840000000} // 对应June 29, 2022 8:33:00 AM Timestamp.now(); // {"seconds":1656491580,"nanoseconds":840000000} // 对应June 29, 2022 8:33:00 AM // 原生接口获取Unix时间戳结果同样错误 (new Date()).getTime(); //1656491580000 // 对应June 29, 2022 8:33:00 AM
该问题是在手机系统设置中手动将设备时间调快1小时后出现的
在修改设备本地时间的场景下,如何才能获取到准确的时间戳值?
解决方案
所有客户端原生时间API(包括JS的Date对象、Firebase客户端的Timestamp.now())都直接读取设备系统时钟返回结果,只要用户手动修改系统时间、或设备硬件时钟走时不准,返回的时间戳必然存在偏差,不存在纯客户端层面的修复方式,必须引入可信的外部时间源:
- 优先复用Firestore自带的服务端时间能力
- 写入业务数据需要记录时间时,直接使用
firebase.firestore.FieldValue.serverTimestamp()作为字段值,该时间由Firestore服务端生成,完全不受客户端时间设置影响,可信度最高。 - 如果需要在客户端拿到当前可信时间,不需要额外搭建服务:写入操作完成后监听对应文档的快照,即可拿到服务端落库返回的准确时间字段;如果不需要触发写入,可以单独维护一个存储公共时间戳的文档,在应用启动、前后台切换时读取一次文档内预存的服务端时间戳,计算出和本地时钟的差值,后续取时间时用本地时钟值减去差值即可,注意控制读取频率避免产生额外资费。
- 写入业务数据需要记录时间时,直接使用
- 有自建服务端的场景,可以直接在服务端提供时间查询接口,客户端定时请求接口拿到服务端标准时间,同样通过计算时钟差值的方式,在两次请求间隔内本地计算准确时间即可,注意定期更新差值抵消设备时钟的走时误差。
注意事项
所有涉及核心业务逻辑的时间判断(比如活动有效期校验、订单时长计算、权限时效判断),绝对不能信任客户端本地生成的时间戳,必须以服务端返回的时间为准,避免恶意用户通过修改本地时间绕过业务限制。
内容的提问来源于stack exchange,提问作者Bhaumik Surani
相关产品推荐
相关产品推荐

