Cloud Firestore:通过多个UTC偏移量存储和查询今天的日期吗? [英] Cloud Firestore: Storing and querying for today's date over multiple UTC offsets?

查看:51
本文介绍了Cloud Firestore:通过多个UTC偏移量存储和查询今天的日期吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Firestore编写一个Web应用程序,该应用程序必须能够显示今天的热门帖子",并且在考虑不同时区的用户时遇到了无法正确查询的问题.

I'm writing a web app using Firestore that needs to be able to show "Today's Popular Posts" and I'm having trouble getting the queries right when considering users in different timezones.

日期以UTC 0的形式存储在数据库中,然后通过 Moment.js在客户端中调整为当前用户的UTC偏移量..这可以正常工作.

The dates are stored in the DB as UTC 0, then adjusted to the current user's UTC offset in the client via Moment.js. This works correctly.

添加新帖子时,我使用 firebase.firestore.FieldValue.serverTimestamp()将当前服务器的时间戳存储在名为 timestamp 的字段中,如下所示:

When adding a new post I use firebase.firestore.FieldValue.serverTimestamp() to store the current server timestamp in a field called timestamp, like so:

const collectionRef = db.collection('posts');
collectionRef.add({
  name: "Test Post",
  content: "Blah blah blah",
  timestamp: firebase.firestore.FieldValue.serverTimestamp(),
  likeCount: 0
});

然后在服务器上,我有一个Cloud函数,该函数在create上运行,并将另一个字段添加到名为 datestamp 的文档中,这是UTC 0时间戳,但已进行了调整,以使时间成为那天.该函数如下所示:

Then on the server I have a Cloud Function that runs on create and adds another field to the document called datestamp which is the the UTC 0 timestamp, but adjusted so that the time is the beginning of the day. The function looks like this:

exports.updatePostDate = functions.firestore
  .document('posts/{postID}')
  .onCreate((event) => {
    const db = admin.firestore();
    const postRef = db.doc('post/'+event.params.postID);
    const postData = event.data.data();

    const startOfDay = moment(postData.timestamp).startOf('day').toDate();

    return postRef.update({
      datestamp: startOfDay
    });
  });

存储一个始终是一天中开始时间的时间戳,这使我可以编写这样的查询来查找所有帖子并按给定日期的受欢迎程度进行排序:

Storing a timestamp where the time is always the beginning of the day enables me to write a query like this for finding all posts and ordering by popularity on a given day:

const startOfDayUTC = moment.utc().startOf('day').toDate();
const postQuery = db.collection('posts')
                    .orderBy('likeCount', 'desc')
                    .orderBy('timestamp', 'desc')
                    .where('datestamp', '==', startOfDayUTC)
                    .limit(25);

问题是,当解析帖子的 timestamp 字段时,这可能会显示带有两个不同日期的帖子,具体取决于用户的UTC偏移量.因此,即使查询正确获取了所有表示 datestamp 的帖子,即2018-01-30T00:00:00Z, timestamp 的日期也可能不是相同的一旦解析.这是两个帖子的示例:

The problem is, depending on the user's UTC offset, this can display posts with two different dates when parsing the post's timestamp field. So even though the query is correctly fetching all the posts where the datestamp is say, 2018-01-30T00:00:00Z, the timestamp's date might not be the same once parsed. Here's an example of two posts:

Post 2:
likeCount: 1
timestamp (UTC 0): 2018-01-30T06:41:58Z
timestamp (parsed to UTC-8): 2018-01-29T22:41:58-08:00
datestamp (UTC 0): 2018-01-30T00:00:00Z

Post 1:
likeCount: 0
timestamp (UTC 0): 2018-01-30T10:44:35Z
timestamp (parsed to UTC-8): 2018-01-30T02:44:35-08:00
datestamp (UTC 0): 2018-01-30T00:00:00Z

因此您可以看到,虽然帖子具有相同的 datestamp ,但在将 timestamp 调整为本地UTC之后, timestamp 字段可以最终在两个不同的日子结束.

So you can see, while the posts have the same datestamp, after adjusting the timestamp to the local UTC, the timestamp fields can end up being on two different days.

如果有人对此有解决方案,我将不胜感激.

If anyone has a solution to this I would be very grateful.

推荐答案

在这种情况下,最好避免使用函数,因为您现在可以执行复合查询.您可以简单地使用

I think it is better to avoid functions in this case as you can perform compound queries now. You can simply use

query.where(date > lastMidnight).where(data < now).get().then(...)

可以说只限制一天的数据,并尝试将所有时间变量保留在UTC 0中,只是在客户端找到起点和当前时间,然后将其转换为UTC0.

so to speak to limit data which only belongs to one day and try to keep all your time variables in UTC 0 and just find the start point and the current time both client side and convert them to UTC0.

//get local time from midnight to now (local)
const now = new Date();
const lastMidnight = now.setHours(0,0,0,0);

//then convert those to UTC0 to pass on in your query to firestore
const lastMidNightUTC = new Date(lastMidnight + now.getTimezoneOffset() * 60000).toString();
const nowInUTC = new Date(now + now.getTimezoneOffset() * 60000).toString();

您可以获取数据(请记住,您需要创建索引或只运行一次查询,firebase SDK会为您在开发工具-> console中生成一个用于创建索引的链接)

and you can get your data (remember you need to make an index or just run the query once and firebase SDK will generate a link to create the index in dev tools -> console , for you)

    query.where(date > lastMidNightUTC).where(data < now).get().then(...)

这篇关于Cloud Firestore:通过多个UTC偏移量存储和查询今天的日期吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆