0

I'm very new to Javascript, and can't figure out the correct formulas to determine how many days have been used vs not used.

I am trying to create a basic form calculator. It has 2 fields, Billing Cycle Date, and Plan Change Date. It should calculate the difference between the two numbers.

The issue is sometimes the Billing Cycle Date is lower than the Plan Change date which results in a negative number which throws off my current formula.

What am I doing wrong?

I have tried different formulas and even tried displaying only positives.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>


    <form>
        <input placeholder="Billing Cycle Date" type="text" onChange="calc()" id="BillingCycleDate"/>
        <input placeholder="Plan Change Date" type="text" onChange="calc()" id="PlanChangeDate"/>
        <input type="button" onClick="calc()" value="Calculate" />
    </form>

    <div id="BillingCycleDate_Result"></div>
    <div id="PlanChangeDate_Result"></div>
    <div id="DaysUsed_Result"></div>
    <div id="DaysUnused_Result"></div>
    <div id="DaysUsedDaysUnused_Result"></div>


<script>
    function calc(){

        //Imports data from form - Billing Cycle Date
        var BillingCycleDateJS=document.getElementById('BillingCycleDate').value;
        //Imports data from form - Plan Change Date
        var PlanChangeDateJS=document.getElementById('PlanChangeDate').value;

        //Calculates - Used Days
        var DaysUsed=+BillingCycleDateJS-PlanChangeDateJS;
        //Calculates - Unused Days
        var DaysUnused=+PlanChangeDateJS-BillingCycleDateJS;
        //Calculates - Days Used & Unused (Should always = 30)
        var DaysUsedDaysUnused=DaysUsed+DaysUnused;

        //Prints Result - Data Billing Cycle Date
        document.getElementById('BillingCycleDate_Result').innerHTML='<br>Billing Cycle Date: ' + BillingCycleDateJS + '<br><br>';
        //Prints Result - Plan Change Date
        document.getElementById('PlanChangeDate_Result').innerHTML='Plan Change Date: ' + PlanChangeDateJS + '<br><br>';

        //Prints Result - Days Used
        document.getElementById('DaysUsed_Result').innerHTML='Days Used: ' + DaysUsed + '<br><i>(If billing cycle = 1 & plan change date = 10, answer should be: 9)<br>(If billing cycle = 10 & plan change date = 1, answer should be: 21)</i><br><br>';
        //Prints Result - Data Unused
        document.getElementById('DaysUnused_Result').innerHTML='Days Unused: ' + DaysUnused + '<br><i>(If billing cycle = 1 & plan change date = 10, answer should be: 21)<br>(If billing cycle = 10 & plan change date = 1, answer should be: 9)</i><br><br>';
        //Prints Result - Billing Cycle Date + Plan Change Date
        document.getElementById('DaysUsedDaysUnused_Result').innerHTML='Days Used+Unused: ' + DaysUsedDaysUnused + '<br><i> (Billing Cycle+Plan Change, Should always = 30)</i>';

    return false
    }

</script>
</body>
</html>

If billing date = 1
If plan change date = 10

Actual Results:
Days Used: -9
Days Unused: 9

Expected Results:
Days Used: 9
Days Unused: 21


If billing date = 10
If plan change date = 1

Actual Results:
Days Used: 9
Days Unused: -9

Expected Results:
Days Used: 21
Days Unused: 9

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • 1
    Java is to Javascript as Pain is to Painting, or Ham is to Hamster. They are completely different. It is highly recommended that aspiring coders try to learn the name of the language they're attempting to write code in. When you post a question, please tag it appropriately. – CertainPerformance Sep 15 '19 at 21:28
  • 1
    https://stackoverflow.com/a/245073/870729 – random_user_name Sep 15 '19 at 22:35

2 Answers2

0

You simply got your math wrong:

//Calculates - Used Days
var DaysUsed=+BillingCycleDateJS-PlanChangeDateJS;
//Calculates - Unused Days
var DaysUnused=+PlanChangeDateJS-BillingCycleDateJS;
//Calculates - Days Used & Unused (Should always = 30)
var DaysUsedDaysUnused=DaysUsed+DaysUnused; 

DaysUnused in you case would always by the negative of DaysUsed. If they must add to 30, just do:

DaysUnused = 30 - DaysUsed.

If DaysUsed is negative, you can add 30 to get the complement:

DaysUsed=+BillingCycleDateJS-PlanChangeDateJS;
DaysUsed = DaysUsed < 0 ? DaysUsed + 30 : DaysUsed;
Kfir Dadosh
  • 1,411
  • 9
  • 9
  • This will not work. If the billing date is `10` and the plan change date is `1`, then the expected result of `DaysUsed` is `21` but the result with your code would be `9`. With date interval calculations, you can't just take the absolute value. – B. Fleming Sep 15 '19 at 22:11
0

The fundamental problem with your calculation is that you're not taking directionality into account. If billing < change, then you should be calculating change - billing. Otherwise, if billing > change, you need to account for the additional days accumulated by transitioning into the next month, which would be 30 + change - billing. That lack of including additional days during month transitions is what's giving you problems.

Notice that the only difference in those calculations above is whether or not the extra 30 is added to the total. Also notice that the result will always be less than 30. You can therefore take advantage of the modulo % operator.

In case you're unaware, the modulo operator takes an expression of the form a % b where a and b are both numbers, and the result will be the "remainder" of a/b. You can visualize the expected result of the modulo operator with the following code:

function modulo(a, b) {
    while(a > b) {
        a -= b;
    }

    return a;
}

(Please note that the above is a gross over-simplification of the modulo operator and that the above is only suitable for cases where a and b are both positive numbers.)

With the above operator in mind, we can take full advantage of it by adding 30 days to our calculated result to simulate a month rollover, and then ensuring that the total is reduced to below 30 in case the rollover was unnecessary.

var DaysUsed = (30 + (+PlanChangeDateJS-BillingCycleDateJS)) % 30;

Since we know that DaysUsed + DaysUnused == 30 is a constraint, we can then calculate DaysUnused by doing the following:

var DaysUsed = (30 + (+PlanChangeDateJS-BillingCycleDateJS)) % 30;
var DaysUnused = 30 - DaysUsed;
B. Fleming
  • 7,170
  • 1
  • 18
  • 36
  • Thank you so much for your help! I really appreciate it. Also, thank you for going above and beyond by expanding my knowledge of JS with the modulo operator. If I understand correctly, the modulo operator works like this.... If = positive number, Do math equation #1 If = negative number, Do math equation #2 – JamesMiller Sep 15 '19 at 22:48
  • @JamesMiller Not quite. Imagine dividing two numbers. The result is the numerator of the unreduced fractional component in the result. For example, take `17 % 5`. If we do `15 / 9`, the unreduced fractional result is `1 6/9`. The fractional component is `6/9`. The numerator is `6`. Therefore, `15 % 9` gives us `6`. This is what we call the "remainder" when dividing two numbers. – B. Fleming Sep 15 '19 at 23:14
  • Oh, I was way off. Thank you for the clarification. I get it now :) – JamesMiller Sep 16 '19 at 00:52
  • @JamesMiller No problem (and it looks like I forgot to change `17 % 5` to `15 % 9`--my bad!). If either my answer or Kfir's answers your question, please be sure to accept one of them so future viewers will know that the question has been resolved :) – B. Fleming Sep 16 '19 at 01:48