Home > Software design >  How to construct the right datetime ranges for timezoned clients using Firestore?
How to construct the right datetime ranges for timezoned clients using Firestore?

Time:11-09

I have a Cloud function that runs everyday, every 10 mins. It calculates some numbers regarding orders and customers for each restaurant branch.

Every branch has working hours, for example:

06:00 - 03:00 (24H) This means from 6:00 Tuesday to 3:00 Wednesday.

I made the function so that it handles the current day hours and whatever that is left of the previous day.

Tuesday(remaining 3 hours for Monday):
00:00 - 03:00
Tuesday:
06:00 - 23:59:59:999

Here's how the code handles generating the ranges:

const getRangeForOneDay = async (forPreviousDay = false) => {
  const lowerBound = "06:00"
  const upperBound = "03:00";


  const lowerBoundSplit = ["06", "00"];
  const startOfToday = new Date();
  startOfToday.setHours(
    forPreviousDay ? 0 : parseInt(lowerBoundSplit[0]),
    forPreviousDay ? 0 : parseInt(lowerBoundSplit[1]),
    0,
    0
  );


  const upperBoundSplit = ["03", "00"];
  const endOfToday = new Date();
  endOfToday.setHours(
    forPreviousDay ? parseInt(upperBoundSplit[0]) : 23,
    forPreviousDay ? parseInt(upperBoundSplit[1]) : 59,
    forPreviousDay ? 0 : 59,
    forPreviousDay ? 0 : 999
  );
  return [startOfToday, endOfToday];
};

const rangeToday = getRangeForOneDay(false);
const rangeYesterday = getRangeForOneDay(true);

const ranges = [rangeToday, rangeYesterday];

const branchId = "some real id";

for (const range of ranges) {
  const [startOfToday, endOfToday] = range;
  const orders = await admin
    .firestore()
    .collection("Orders")
    .where("branch_id", "==", branchId)
    .where("create_on", ">=", startOfToday)
    .where("create_on", "<=", endOfToday)
    .orderBy("create_on", "desc")
    .get();

  console.log(`Orders length = ${orders.size}`);
}


Here's how the ranges would look like:

Current Day(Tuesday):
From Date = 2022-11-08T06:00:00.000Z
To Date = 2022-11-08T23:59:59.999Z

Previous Day(Monday remaining hours data):
From Date = 2022-11-08T00:00:00.000Z
To Date = 2022-11-08T03:00:00.000Z

Both ranges are correct. You can see that the second range is for the previous day calculations, yet it takes place during the first 3 hours of the current day(Monday), which is also what I want.

My problem is that, for the second range, the query always returns 0. Despite creating an order between 12AM and 3AM Today(Tuesday) Nov 11th. The order I created was at 12:44:33 AM, but still it does not show up!

What am I doing wrong in the ranges?

I just want the code to work for this exact case. The normal case(first range), should work fine I think.

By the way, the timezone I am in is Toronto(-5). Though I don't think it matters since Firestore saves dates in UTC, just displays them on the Cloud Firestore in local timezone.

enter image description here

CodePudding user response:

The time ranges in output are in UTC (notice the Z instead of -05:00). If the time range is supposed to be Toronto time then you'll have to convert it first. Try using luxon and refactoring to code as shown below:

import { DateTime } from "luxon";

const getRangeForOneDay = () => {
  const today = DateTime.now().setZone("America/Toronto").startOf("day");

  return [
    [today.toJSDate(), today.plus({ hour: 3 }).toJSDate()],
    [today.set({ hour: 6 }).toJSDate(), today.endOf("day").toJSDate()],
  ];
};

The time ranges that you've mentioned are technically on the same day of your timezone or I renamed the var names above.

const ranges = getRangeForOneDay();
console.log('>>> ranges', ranges)

const branchId = "some real id";

for (const range of ranges) {
  const [startOfToday, endOfToday] = range;
  const orders = await admin
    .firestore()
    .collection("Orders")
    .where("branch_id", "==", branchId)
    .where("create_on", ">=", startOfToday)
    .where("create_on", "<=", endOfToday)
    .orderBy("create_on", "desc")
    .get();

  console.log(`Orders length = ${orders.size}`);
}

Now document with time 00:44 should fall in 00:00 - 03:00 UTC-5 time range.

  • Related