Variable comparison not testing properly

I have a form where the user can select a date using a series of dropdowns for Month, Day, Year. Upon selecting them all I want to test it to make sure that the date selected is not today’s date, nor a weekend date, if so, I want to show them an alert and return them to the form to make an adjustment.

The code below is working fine for the weekend test, and when I use the alert to show me what values are being created I see that both tripDate and todaysDate SHOW me the same values, IF test is not working (just for todays test, the weekend test is working).

Hoping someone much more familiar in javascript (which is pretty much anyone other than me, I compiled this from several google searches and a VERY basic understanding of javascript) can point out to me what I am overlooking.

Thank you for your assistance!

Greg


<script type="text/javascript">
  function isTodayorWeekend() {
    var todaysDate = new Date();
    todaysDate.setHours(0,0,0,0);
    var tripDate = new Date();
    tripDate.setFullYear(document.getElementsByName('pickupdate-year')[0].value);
    tripDate.setMonth(document.getElementsByName('pickupdate-month')[0].value);
    tripDate.setDate(document.getElementsByName('pickupdate-day')[0].value);
    tripDate.setHours(0,0,0,0);
    alert('Today is: ' + todaysDate + '\
' + 'Trip Date: ' + tripDate);
    if(tripDate.getDay() == 6 || tripDate.getDay() == 0 || tripDate == todaysDate)
    {
      alert('Not today or weekends!');
    }
  }
</script>

When I test that same code with my own HTML, the code works fine, so you may need to show us the HTML code that you are using in relation to that function.

Here is the HTML, it is dynamically created via PHP to update the selected option to match the current date (+1 day to minimize people trying to schedule “same day” transportation requests) but this is the final output. Once I get this javascript functioning properly I am most likely going to change the call to the function happen upon form submission, I just have it triggered at the change events for this dropdown now to allow testing to be more direct.


<label>Pickup Date</label>
<select name="pickupdate-month" onchange="isTodayorWeekend()">
<option value="0">January</option>
<option value="1">February</option>
<option value="2">March</option>
<option value="3">April</option>
<option value="4">May</option>
<option value="5" selected="selected">June</option>
<option value="6">July</option>
<option value="7">August</option>
<option value="8">September</option>
<option value="9">October</option>
<option value="10">November</option>
<option value="11">December</option>
</select>
<select name="pickupdate-day" onchange="isTodayorWeekend()">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29" selected="selected">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
<select name="pickupdate-year" onchange="isTodayorWeekend()">
<option value="2013" selected="selected">2013</option>
<option value="2014">2014</option>
<option value="2015">2015</option>
<option value="2016">2016</option>
</select>

When you change one of the select boxes, does the Trip Date that is alerted to you show a similar change?

Yes, the alerts show just as I would expect them too, it is just the IF clause for comparing tripDate and todaysDate that doesn’t validate (even though the alert box shows me the EXACT same data for each of those 2 values. So unless the “background” data is something different than what gets displayed in the alert then I am completely baffled as to why it fails

Ahh, I see. It’s currently the weekend for me now so it’s trickier than usual to test that the day is not the weekend but is the same as todays date.

The issue you’re facing is because you are trying to compare two different objects. Each object may have the same values for their year month and day, but because they are different objects they will always compare as not being the same as the other.

So you can have the following code that compares falsely to all forms of comparison.


var d1 = new Date();
var d2 = new Date();

console.log(d1 > d2) // false
console.log(d1 < d2) // false
console.log(d1 === d2) // false
console.log(d1 == d2) // false

What does work though, is to use the .getTime() method which retrieves a numeric value for that particular date, which does compare well.


var d1 = new Date();
var d2 = new Date();

console.log(d1.getTime() > d2.getTime()) // true

Thank you! After some trial and error I finally got the following code to process as I want it (from the testing I’ve done so far, going to have to wait for the weekend to pass to test it more but pretty sure this is handling it. Now just have to determine when the best time to run this should be (and how to most gracefully inform the end user and have them respond).


<script type="text/javascript">
  function isTodayorWeekend() {
    var todaysDate = new Date();
    todaysDate.setHours(0,0,0,0);
    var tripDate = new Date();
    tripDate.setHours(0,0,0,0);
    tripDate.setFullYear(document.getElementsByName('pickupdate-year')[0].value);
    tripDate.setMonth(document.getElementsByName('pickupdate-month')[0].value);
    tripDate.setDate(document.getElementsByName('pickupdate-day')[0].value);
    //alert('Today is: ' + todaysDate + '\
' + 'Trip Date: ' + tripDate);
    if(tripDate.getDay() == 6 || tripDate.getDay() == 0 || tripDate.getTime() == todaysDate.getTime())
    {
      alert('You have chosen today\\'s date or a weekend');
    }
  }
</script>

As a minor improvement, you may want to break out the checking if it’s a weekend, or if it’s today, to separate functions.


function isWeekday(date) {
    return date.getDay() === 6 || date.getDay() === 0;
}

function isToday(date) {
    var today = new Date();

    today.setHours(0, 0, 0, 0);
    date.setHours(0, 0, 0, 0);

    return date.getTime() === today.getTime();
}

...

function isTodayorWeekend() {
    var tripDate = new Date();
    tripDate.setFullYear(document.getElementsByName('pickupdate-year')[0].value);
    tripDate.setMonth(document.getElementsByName('pickupdate-month')[0].value);
    tripDate.setDate(document.getElementsByName('pickupdate-day')[0].value);
  
    if(isWeekday(tripDate) || isToday(tripDate)) {
      alert('You have chosen today\\'s date or a weekend');
    }
}

See how that simplifies the functions so that you can now easily tell at a glance what is happening?

If you want to use that isToday() function in some other code though, there is a side-effect from the technique that is currently being used. Currently the isToday() function changes the time parts of the date. Those changes will remain in effect after the function has finished, so if other code relies on some of the time parts of a date being checked, that will result in a problem.

The solution to this is to not change the time parts of the date that is being checked.
One simple solution is to set the time parts of todays date to be the same as the date that we are checking:


function isToday(date) {
    var today = new Date();

    // We only want to compare the day month year parts of the date, so set the other parts to be the same
    today.setHours(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());

    return date.getTime() === today.getTime();
}

Another technique that results in less confusion about what is going on, is to just check the year month and day, which results in a function that is much easier to understand.


function isToday(date) {
    var today = new Date();

    return date.getFullYear() === today.getFullYear() &&
        date.getMonth() === today.getMonth() &&
        date.getDate() === today.getDate();
}

Perfect! Thank you, I have rewritten my code using your recommendations and then set the call to javascript to occur onmouseover for the submit button, that way if the date is not correct they are notified and can’t submit the form until they have corrected the date to meet our requirements. Perfect!

Now on to my next adjustment for this site.

Greg