如何解决Flutter向Firestore存DateTime出现1小时时间偏差的问题?
问题根因
- Firestore 存储时间类型字段时默认采用UTC 标准时间,你代码中
Services.getTime()返回的DateTime对象为本地时区时间,若你所处时区为 UTC+1,本地时间 2021-10-11 12:16 对应的 UTC 时间就是 2021-10-11 11:16,就会出现存储值比传入值少1小时的表现。 - Firestore 控制台展示时间戳时也默认用 UTC 时间,即使你存入的是带时区的
DateTime,也会自动转换为 UTC 格式存储,不会保留本地时区偏移。
解决方案
方案1:统一用UTC时间存储(官方推荐)
这是跨时区场景下的最佳实践,存储时统一转UTC,读取时再转本地时区展示即可,示例代码如下:
// 拿到本地时区时间 final localDateTime = await Services.getTime(); // 转换为UTC时间后存入Firestore final utcDateTime = localDateTime.toUtc(); await FirebaseFirestore.instance.collection('trialUsers').doc('someRandomID').set({ "name": user.user.displayName, "email": user.user.email, "creationDate": utcDateTime, }).then((value) => print(utcDateTime));
读取时转换为本地时间展示:
// 从Firestore读取到Timestamp类型后转换 final storedTs = documentSnapshot.get('creationDate') as Timestamp; final showTime = storedTs.toDate().toLocal();
方案2:直接使用Firestore服务器时间戳
避免客户端本地时间不准导致的问题,直接用Firebase服务器生成时间戳:
await FirebaseFirestore.instance.collection('trialUsers').doc('someRandomID').set({ "name": user.user.displayName, "email": user.user.email, "creationDate": FieldValue.serverTimestamp(), });
方案3:存储为固定格式字符串(不推荐跨时区使用)
如果你的应用仅在单一时区使用,不需要兼容跨时区场景,可以把时间转成字符串存储,不会自动触发时区转换:
import 'package:intl/intl.dart'; final dateTime = await Services.getTime(); final timeStr = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime); await FirebaseFirestore.instance.collection('trialUsers').doc('someRandomID').set({ "name": user.user.displayName, "email": user.user.email, "creationDate": timeStr, });
内容的提问来源于stack exchange,提问作者Martin Wittick
相关产品推荐
相关产品推荐

