0

I am facing some issue while calculating the time difference between two dates using the JavaScript. I am providing my code below.

Here I have cutoff time and dep_time value. I have to calculate today's date with dep_date and if today's date and time is before the cutoff time then it will return true otherwise false. In my case its working fine in Chrome but for same function it's not working in Firefox. I need it to work for all browsers.

function checkform() {
  var dep_date = $("#dep_date1").val(); //07/27/2019
  var cut_offtime = $("#cutoff_time").val(); //1
  var dep_time = $("#dep_time").val(); //6:00pm
  var dep_time1 = dep_time.replace(/[ap]/, " $&");
  var todayDate = new Date();
  var todayMonth = todayDate.getMonth() + 1;
  var todayDay = todayDate.getDate();
  var todayYear = todayDate.getFullYear();
  if (todayDay < 10) {
    todayDay = "0" + todayDay;
  }
  if (todayMonth < 10) {
    todayMonth = "0" + todayMonth;
  }
  //console.log('both dates',todayMonth,todayDay,todayYear);
  var todayDateText = todayMonth + "-" + todayDay + "-" + todayYear;
  var inputToDate = Date.parse(dep_date.replace(/\//g, " "));
  var todayToDate = Date.parse(todayDateText.replace(/-/g, " "));
  console.log("both dates", dep_date, todayDateText);
  if (inputToDate >= todayToDate) {
    var date = new Date();
    var hours = date.getHours();
    var minutes = date.getMinutes();
    var ampm = hours >= 12 ? "pm" : "am";
    hours = hours % 12;
    hours = hours ? hours : 12; // the hour '0' should be '12'
    minutes = minutes < 10 ? "0" + minutes : minutes;
    var strTime = hours + ":" + minutes + " " + ampm;
    var timeStart = new Date(todayDateText + " " + strTime);
    var timeEnd = new Date(dep_date + " " + dep_time1);
    var diff = (timeEnd - timeStart) / 60000; //dividing by seconds and milliseconds
    var minutes = diff % 60;
    var hours = (diff - minutes) / 60;
    console.log("hr", hours);
    if (parseInt(hours) > parseInt(cut_offtime)) {
      return true;
    } else {
      alert("You should book this trip before " + cut_offtime + " hr");
      return false;
    }
  } else {
    alert("You should book this trip before " + cut_offtime + " hr");
    return false;
  }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
satya
  • 3,508
  • 11
  • 50
  • 130
  • 2
    What do you mean with "it's not working with Firefox"? What's it doing or not doing? Any errors? – AKX Jul 17 '19 at 08:40
  • 1
    do you really need to reinvent the wheel? why not use moment.js or something similar ? – madalinivascu Jul 17 '19 at 08:40
  • 1
    It’s much easier to calculate time difference by subtracting just the `getTime()` value of both Date objects! – Kokodoko Jul 17 '19 at 08:43
  • @AKX: means for `dep_date=07/27/2019` and other given input it should return true which is happening in chrome but it firefox its returns false. – satya Jul 17 '19 at 08:43
  • Re `Date.parse(dep_date.replace(/\//g, " "))`, see [*Why does Date.parse give incorrect results?*](https://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results) I would expect it to return an invalid date in a number of implementations. Consider the logic of parsing a string to create another string to give to another parser that you have no control over, or you can give the parts directly to the Date constructor and be certain of the result. – RobG Jul 17 '19 at 10:25
  • [What are valid Date Time Strings in JavaScript?](https://stackoverflow.com/questions/51715259/what-are-valid-date-time-strings-in-javascript) – str Jul 17 '19 at 11:10

1 Answers1

0

Part of your issue is here:

var todayDateText = todayMonth + "-" + todayDay + "-" + todayYear;
var inputToDate = Date.parse(dep_date.replace(/\//g, " "));

The first line generates a string like "07-17-2019". The next changes it to "07 17 2019" and gives it to the built–in parser. That string is not a format supported by ECMA-262 so parsing is implementation dependent.

Chrome and Firefox return a date for 17 July 2019, Safari returns an invalid date.

It doesn't make sense to parse a string to get the values, then generate another string to be parsed by the built–in parser. Just give the first set of values directly to the Date constructor:

var inputToDate = new Date(todayYear, todayMonth - 1, todayDay);

which will work in every browser that ever supported ECMAScript.

Similarly:

var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? "pm" : "am";
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? "0" + minutes : minutes;
var strTime = hours + ":" + minutes + " " + ampm;
var timeStart = new Date(todayDateText + " " + strTime);

appears to be a lengthy and brittle way to copy a date and set the seconds and milliseconds to zero. The following does exactly that in somewhat less code:

var date = new Date();
var timeStart = new Date(date);
timeStart.setMinutes(0,0);

use

var timeStart = new Date(todayDateText + " " + strTime)

Applying these changes to your code gives something like:

function parseMDY(s) {
  var b = s.split(/\D/);
  return new Date(b[2], b[0]-1, b[1]);
}

function formatDate(d) {
  return d.toLocaleString(undefined, {
    day: 'numeric',
    month: 'short',
    year: 'numeric'
  });
}

// Call function with values
function checkform(dep_date, cut_offtime, dep_time) {
  
  // Helper
  function z(n) {
    return (n<10?'0':'') + n;
  }
  
  // Convert dep_date to Date
  var depD = parseMDY(dep_date);

  // Get the departure time parts
  var dtBits = dep_time.toLowerCase().match(/\d+|[a-z]+/gi);
  var depHr = +dtBits[0] + (dtBits[2] == 'pm'? 12 : 0);
  var depMin = +dtBits[1];
  
  // Set the cutoff date and time
  var cutD = new Date(depD);
  cutD.setHours(depHr, depMin, 0, 0);

  // Get current date and time
  var now = new Date();
  
  // Create cutoff string
  var cutHr = cutD.getHours();
  var cutAP = cutHr > 11? 'pm' : 'am';
  cutHr = z(cutHr % 12 || 12);
  cutMin = z(cutD.getMinutes());
  var cutStr = cutHr + ':' + cutMin + ' ' + cutAP;
  var cutDStr = formatDate(cutD);
  
  // If before cutoff, OK
  if (now < cutD) {
    alert('Book before ' + cutStr + ' on ' + cutDStr);
    return true;
  
  // If after cutoff, not OK
  } else {
    alert('You should have booked before ' + cutStr + ' on ' + cutDStr);
    return false;
  }
}

// Samples
checkform('07/27/2019','1','6:00pm');
checkform('07/17/2019','1','11:00pm');
checkform('07/07/2019','1','6:00pm');

That refactors your code somewhat, but hopefully shows how to improve it and fix the parsing errors.

RobG
  • 142,382
  • 31
  • 172
  • 209