skip to Main Content

In each record that I save to MongoDB, I execute it with Date.noe, example:

   createdAt: {
        type: Date,
        default: Date.now
    }

So in mongoDB I have the record saved as follows:

createdAt: 2023-02-01T01:39:03.377+00:00

In React I get the records and in this way I show the date using DayJS:

dayjs(createdAt).format('DD/MM/YY')

But the problem is that the date indicates that the registration was made on 02-2023-01 but when using DayJS the date changes to 01-31-2023

Changing the day decreases the record by one day and this is causing me conflicts since they are about financial records.

On my server I don’t have any time stamp, I use MongoDB from Atlas (cloud.mongodb)

This is my query to mongoDB where when requesting the information for the month of February, it correctly returns this, but in React if the record is from February 1, 2023, it shows me February 31, 2023:

db.purchases.aggregate([
    {
        $match: {
            "detail.category._id": ObjectId("63bf4d0b10dfcae061b6eab0")
        }
    },
    {
        $unwind: "$detail"
    },
    {
        $group: {
            _id: "$detail.category._id",
            total: { $sum: "$total" },
            totalProductPurchases: { $sum: "$detail.quantity" },
            purchasesCount: { $sum: 1 },
            purchases: {
                $push: {
                    $cond: [
                        {
                            $and: [
                                { $eq: [{ $year: "$createdAt" }, 2023] },
                                { $eq: [{ $month: "$createdAt" }, 2] },
                                { $gte: [{ $dayOfMonth: "$createdAt" }, 1] },
                                { $lte: [{ $dayOfMonth: "$createdAt" }, 31] }
                            ]
                        },
                        { 
                            purchaseId: "$_id",
                            month: { $month: "$createdAt" },
                            isoWeek: { $isoDayOfWeek: "$createdAt" },
                            dayOfMonth: { $dayOfMonth: "$createdAt" }, 
                            createdAt: "$createdAt",
                            total: "$total",
                            subtotal: "$subtotal",
                            tax: "$tax",
                            discount: "$discount",
                            totalBeforeTax: "$totalBeforeTax",
                            createdAt: "$createdAt",
                            paymentType: "$paymentType"
                        },
                        false 
                    ]
                }
            },
             product_counts: { 
                $push: {
                    product: "$detail.name",
                    count: "$detail.quantity"
                }            },
            }
    },
    {
        $unwind: "$product_counts"
    },
    {
        $group: {
            _id: "$product_counts.product",
            ProductPurchasesNumber: { $sum: "$product_counts.count" },
            purchases: { $first: "$purchases"},
            totalProductPurchases: { $first: "$totalProductPurchases"},
            total: { $first: "$total"},
            purchasesCount: { $first: "$purchasesCount"}
        }
    },
    {
        $sort: { count: -1 }
    },
    {
        $limit: 3
    },
    {
        $group: {
            _id: null,
            top3Products: { $push: { product: "$_id", ProductPurchasesNumber: "$ProductPurchasesNumber" } },
            total: { $first: "$total" },
            totalProductPurchases: { $first: "$totalProductPurchases" },
            purchasesCount: { $first: "$purchasesCount" },
            purchases: { $first: "$purchases" }
        }
    },
    {
        $addFields: {
            purchasesArrayLength: { $size: "$purchases" },
            filteredPurchases: {
                $filter: {
                    input: "$purchases",
                    as: "purchase",
                    cond: { $ne: [ "$$purchase", false ] }
                }
            }
        },
    },
    {
        $project: {
            purchases: 0
        }
    } 
])

How can I avoid these kinds of errors? Thank you.

2

Answers


  1. If you only want to retrieve records matching dates in the client-side timezone, send the dates in the API call.

    For example, on the React side

    // These will be local date instances
    const startDate = new Date(2023, 1, 1); // Start of day Feb 1st
    const endDate = new Date(2023, 2, 1, 0, 0, -1); // End of day Feb 28
    
    const params = new URLSearchParams({
      startDate: startDate.toISOString(),
      endDate: endDate.toISOString(),
    });
    
    fetch(`/api/purchases?${params}`)
      .then(...);
    

    and on the server-side, parse the dates from the query string and use them in your MongoDB aggregate query

    const startDate = new Date(req.query.startDate);
    const endDate = new Date(req.query.endDate);
    
    Login or Signup to reply.
  2. Your requirements and questions are not really clear to me, but I would write the conditions like this:

    {
       $cond: [
          {
             $eq: [
                { $dateTrunc: { date: "$createdAt", unit: 'month', timezone: 'America/New_York' } },
                DateTime.local({ zone: "America/New_York" }).startOf('month').toJSDate()
             ]
          },
          ...
       ]
    }
    

    or

    {
       $cond: [
          {
             $and: [
                { $gte: ["$createdAt", DateTime.local({ zone: "America/New_York" }).startOf('month').toJSDate()] },
                { $lte: ["$createdAt", DateTime.local({ zone: "America/New_York" }).endOf('month').toJSDate()] }
             ]
          },
          ...
       ]
    }
    

    I prefer luxon over Day.js, I think the same function are also available in Day.js.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search