Search code examples
javascriptnode.jsdate

How to subtract two dates and time in Node.js?


I want to achieve the following when I cancel my subscription:

nextBillingTime: 2024-05-10T14:59:58.582+00:00

paypalSubscriptionCancelledAt: 2024-05-07T11:59:18.000+00:00

subscriptionPeriodDuration: 3 days, 3 hours, 0 minutes, 40 seconds

I have the following code:

paypalRouter.post("/cancel-subscription/webhook", async (req, res) => {
  try {
    const webhookEvent = req.body;

    if (verifyResponse.data.verification_status === "SUCCESS") {
      if (webhookEvent.event_type === "BILLING.SUBSCRIPTION.CANCELLED") {
        const userId = webhookEvent.resource.custom_id;
        const subscriptionId = webhookEvent.resource.id;
        const nextBillingTime = webhookEvent.resource.billing_info.next_billing_time;
        const paypalSubscriptionCancelledAt = webhookEvent.resource.status_update_time;

        try {
          const updatedUserCancelSubscription = await User.findOneAndUpdate(
            { _id: userId, subscriptionId: subscriptionId },
            {
              $set: {
                suscriptionStatusCancelled: true,
                subscriptionStatusPending: false,
                subscriptionStatusConfirmed: false,
                nextBillingTime: nextBillingTime,
                isPremium: true,
                paypalSubscriptionCancelledAt: paypalSubscriptionCancelledAt,
                subscriptionPeriodDuration:
              },
            },
            { new: true }
          );

          // ... (other code)
        } catch (error) {
          // ... (error handling)
        }
      }
    } else {
      // ... (other code)
    }
  } catch (error) {
    // ... (error handling)
  }
});

I need help calculating the subscriptionPeriodDuration using the nextBillingTime and paypalSubscriptionCancelledAt dates.


Solution

  • Thank you all for the help. After a bit of struggle, I realized that my logic was incorrect. Instead of focusing on PayPalSubscriptionCancelledAt and subscriptionPeriodDuration, which are static dates, I should create a dynamic date to update nextBillingTime according to my logic. In my case, I created a new property in my mongoose.Schema() getCurrentTimeAfterRefresh, which is a dynamic date and updates each day thanks to node-cron, and I can create the desired logic. Here is the solution to my problem:

    getCurrentTimeAfterRefresh:{
        type: Date,
        required: false,
    },
    

    Implementing node-cron

    let cronJobs = {};
    
    
    if (!cronJobs[userId]) {
    
              //* this is updated each second
            // cronJobs[userId] = cron.schedule("* * * * * *", async () => {
             //* this is updated each day
              cronJobs[userId] = cron.schedule("0 0 * * *", async () => {
    
              try {
                // const users = await User.find({ suscriptionStatusCancelled: true });
                const user = await User.findById(userId);
                if (!user) {
                  console.log(`User not found: ${userId}. Stopping cron job.`);
                  cronJobs[userId].stop();
                  delete cronJobs[userId];
                  return;
                }
                user.getCurrentTimeAfterRefresh = new Date();
                console.log(`Updated getCurrentTimeAfterRefresh for user: ${user._id} to ${user.getCurrentTimeAfterRefresh}`);
    
                  if (user.suscriptionStatusCancelled == true && user.getCurrentTimeAfterRefresh > user.nextBillingTime) {
                    user.isPremium = false;
                    console.log(`Subscription expired for user: ${user._id}. Stopping cron job.`);
    
                     // Stop the cron job and delete it from the object
                     cronJobs[user._id].stop();
                     delete cronJobs[user._id];
                  }
                  
                  await user.save();
                
    
                console.log("Updated subscription times and statuses for cancelled subscriptions");
              } catch (error) {
                console.error("Error updating subscription times and statuses:", error);
              }
            });
          }