我有一个包含下一项的集合,其中一个属性是日期:
id: xxxxxx
name: xxxx
date: August 21, 2018 at 1:00:00 AM UTC+8 (timestamp)
在 Firebase 云函数中,我尝试查询某个时间段内的所有对象,该时间段可以是天、周、年等。
我想按当前服务器日期查询项目,因此我在 Firebase 云函数中执行此操作:
let auxDate = moment();
dateStart = auxDate.startOf('day').toDate();
dateEnd = auxDate.endOf('day').toDate();
await admin.firestore().collection('items')
.where("date", ">=", dateStart)
.where('date', '<=', dateEnd).get();
控制台打印的dateStart和dateEnd的值为:
Date start: Tue Aug 21 2018 00:00:00 GMT+0000 (UTC)
Date end: Tue Aug 21 2018 23:59:59 GMT+0000 (UTC)
查询返回 0 项。但是当我将项目的日期更改为
id: xxxxxx
name: xxxx
date: August 21, 2018 at 8:00:00 AM UTC+8 (timestamp)
查询正确返回项目。
现在我知道问题出在偏移量上,但我该如何解决这个问题?为什么 Firebase 以 UTC+8 保存所有日期?
最佳答案
我找到了我自己问题的答案。我会详细解释。
理解问题:
首先要记住,我们是在云函数内执行此查询,因此我们不知道客户端时区。在 Firestore 中,所有日期均以 UTC+00 格式保存。所以如果我有一个像这样的项目:
id: xxxxxx
name: xxxx
date: August 22, 2018 at 12:00:00 AM UTC+8 (timestamp)
这意味着该日期等于 2018 年 8 月 21 日下午 04:00:00 UTC+0
。
因此,如果我想查询以下日期之间的所有日期:
Date start: August 22, 2018 at 12:00:00 AM UTC+8 (timestamp)
Date end: August 22, 2018 at 11:59:59 PM UTC+8 (timestamp)
这意味着查询必须类似于:
Date start: August 21, 2018 at 04:00:00 AM UTC+0 (timestamp)
Date end: August 22, 2018 at 03:59:59 PM UTC+0 (timestamp)
所以问题是,当我这样做时 let auxDate = moment()
创建一个带有服务器时间且没有偏移量的日期,因此 auxDate 的值例如:2018 年 8 月 21 日下午 11:23:43 UTC+0
。
因此 auxDate 的开始日期变为:
auxDate start: August 21, 2018 at 12:00:00 AM UTC+0 (timestamp)
auxDate end: August 21, 2018 at 11:59:59 PM UTC+0 (timestamp)
正如我们所看到的,这个查询没有满足我们必须查询的范围,并且许多项目将被排除。
问题结论:
如果不知道客户端的时区,我们就无法正确查询。
解决方案:
现在我将客户端的当前时间传递给此云函数并计算开始和结束日期:
const clientCurrentDateTime = "2018-08-22T11:23:15+08:00";
let startDate = moment(clientCurrentDateTime).utcOffset(clientCurrentDateTime).startOf('day').toDate();
let endDate = moment(clientCurrentDateTime).utcOffset(clientCurrentDateTime).endOf('day').toDate();
这会为不同的偏移量/时区创建正确的开始和结束日期时间
关于firebase - 如何正确查询 firestore 和 cloudfunctions 中的日期时间段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51940895/