Ive got a piece of JS that needs to validate and compare a start date and time against an end date and time.
So in other words end date & time cannot be less than start date and time.
Now the problem.
I originally only accepted the time in 24 hour(military) Format. but now let the user choose between 12 hour or 24 hour.
Example 13:00 or 1:00 PM
This piece of code work for 24 hour time format, but not for 12, its 12:00 PM that causes the problem.
So I need to adapt this piece of code to work for either 12 hour or 24 hour, but im not sure how to do this.
function validateStartEndTime() {
var date = document.getElementById("datepickerStart").value;
var dateEnd = document.getElementById("datepickerEnd").value;
if (!isValidDate(date)) {
alert("Not Valid Date");
return false;
}
var start = document.getElementById("timepicker").value;
var end = document.getElementById("timepickerEnd").value;
var stDate = new Date(parse(date +" "+ start));
var enDate = new Date(parse(dateEnd + " "+ end));
var compDate = enDate - stDate;
if (compDate >= 0)
return true;
else {
alert("End time must be greater than Start Time ");
return false;
}
}
You could write a function that converts time in 12 hour format to time in 24 hour format, something like:
function convertTo24HourFormatIfNeeded(timeString) {
var is12HourFormat = timeString.indexOf("M") !== -1;
if (is12HourFormat) {
var isPm = timeString.indexOf("PM") !== -1;
var timeStringNoSuffix = timeString.split(" ")[0];
if (isPm) {
var hoursAndMinutes = timeStringNoSuffix.split(":");
var hours = hoursAndMinutes[0];
var convertedHours = (Number(hours) + 12);
var minutes = hoursAndMinutes[1];
return convertedHours + ":" + minutes;
} else {
return timeStringNoSuffix;
}
} else {
return timeString;
}
}
Then use it in your code:
var start = convertTo24HourFormatIfNeeded(document.getElementById("timepicker").value);
var end = convertTo24HourFormatIfNeeded(document.getElementById("timepickerEnd").value);
If you're not adverse to using external libraries, i found MomentJs to be very handy working with dates, and among other things it allows to parse the date in a user-defined format, so you could build your date string accordingly to user selection of AM/PM or 24-hour format and feed it to moment js.
Related
I am new in the world of programming: D and I have a doubt about the comparison of hours.
I have a sheet with the following information
Name | Time out | Time in |
nam_1 10:00:00
nam_2 09:00:00
Time out hours have been entered using this code:
var start = Utilities.formatDate (new Date (), "Europe / Berlin", "HH: mm: ss");
sheet.appendRow([name, start]);
What I would like to try is:
var time_in = "13:00:00";
if time out> 13:00:00:
sheet.getRange(j+1, 2).setValue(time_in);
The problem is that I do not know exactly how to do it. What I have tried for now is:
function getTimeFromDateStartUserInput(date) {
return Utilities.formatDate(date, "Europe/Berlin", "HH:mm:ss");
}
function insertTimeIn(){
var file = DriveApp.getFilesByName("MySheet");
var doc = SpreadsheetApp.open(file.next());
var sheet = doc.getSheetByName("Sheet1");
if(sheet!=null){
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var time_in = new Date ('30/12/1899 17:00:00');
time_in.setHours(13,0,0,0);
var inFormated = getTimeFromDate(time_in);
for(var i = 0; i<values.length; i++){
if(values[i][1]>=inFormated && values[i][2]=""){
sheet.getRange(j+1, 2).setValue(time_in);
}else{
sheet.getRange(j+1, 2).setValue("Nop");
}
}
}
However, I have not achieved anything with that code.
I think the problem may be that any entry in the "Time out" column has this design: Sat Dec 30 14:51:22 GMT + 01: 00 1899.
Therefore I think it does not work since I am comparing an hour with a complete Date object.
The logical thing I think it would be to call the function getTimeFromDateStartUserInput for all the input of values[i][1] but I do not know how to do it.
Could someone help me with this problem?
This is my guess at what you are trying to do. It doesn't work because it still contains errors. I commented on a few of them but I can't fix them because it's still not clear what you are trying to do..
function insertTimeIn(){
var files = DriveApp.getFilesByName('SpreadsheetName');
var n=0;
while(files.hasNext()){
var file=files.next();
}
if(++n>1){
throw("Error: There is more than one file with that name in function insertTimeIn");
return;
}
if(file.getMimeType()==MimeType.GOOGLE_SHEETS){
var doc=SpreadsheetApp.openById(file.getId());
var sheet=doc.getSheetByName("Sheet1");
if(sheet!=null){
var dataRange=sheet.getDataRange();
var values=dataRange.getValues();
var time_in=new Date(1899,11,30,13,0,0);
var inFormated=Utilities.formatDate(time_in, Session.getScriptTimeZone(), "HH:mm:ss");//it returns a string not a date
for(var i=0;i<values.length;i++){
if(values[i][1]>=inFormated && values[i][2]=""){//informated is a string not a date so greater than doesn't really make much sense here.
sheet.getRange(j+1, 2).setValue(time_in);//j is undefined
}else{
sheet.getRange(j+1, 2).setValue("Nop");//again j is undefined
}
}
}
}
}
A simple answer might be to auto convert the initial timestamp to the current date. I'm not entirely sure what the use of your sheet is going to be but I use a sheet for time entry and use the function onEdit() to verify that the user put the dateTime in correctly.
function onEdit(){
if(cell.getValue() instanceof Date === true){
if(cell.getValue().getFullYear()<2018 ){
formatDate();
}
}
}
function formatDate() {
var timeValue, cell,hour,minute,time,row,dateObj,month,day,year,newDate
cell = SpreadsheetApp.getActive().getActiveCell()
timeValue = cell.getValue()
hour = timeValue.getHours()
minute = timeValue.getMinutes() < 10? '0'+timeValue.getMinutes(): timeValue.getMinutes();
time = hour+":"+minute
row = cell.getRow()
dateObj = new Date();
month = dateObj.getUTCMonth() + 1; //months from 1-12
day = dateObj.getUTCDate();
year = dateObj.getUTCFullYear();
newDate = month + "/" + day + " "+ time; // formatted dateTimestamp to replace timestamp with
cell.setValue(newDate)
}
Let me know if that works for you. In my application, the onEdit function checks the active cell and continues if the entered value is a dateTime. If it is, it check what year the date is (time values alone are automatically 12/30/1899 and therefore throw wild numbers out when getting durations between a dateTimestamp and a timestamp with no date.
This question already has answers here:
Why does Date.parse give incorrect results?
(11 answers)
Closed 5 years ago.
Really not sure where I'm going wrong here.
I have some JavaScript to sort a table by date value:
function sortByDate() {
if (jQuery("#web-orders .data-table tbody").length > 0) {
var tbody = document.querySelector("#web-orders .data-table tbody");
var rows = [].slice.call(tbody.querySelectorAll("tr"));
}
if (jQuery("#store-orders .data-table tbody").length > 0) {
var tbodyStore = document.querySelector("#store-orders .data-table tbody");
var rowsStore = [].slice.call(tbodyStore.querySelectorAll("tr"));
rowsStore.forEach(function (entry) {
rows.push(entry);
});
}
rows.sort(function (a, b) {
console.log("a.cells[2].innerHTML = " + a.cells[2].innerHTML);
console.log("b.cells[2].innerHTML = " + b.cells[2].innerHTML);
a = new Date(Date.parse(a.cells[2].innerHTML));
b = new Date(Date.parse(b.cells[2].innerHTML));
console.log("a = " + a);
console.log("b = " + b);
return a - b;
});
rows.forEach(function (v) {
tbody.appendChild(v); // note that .appendChild() *moves* elements
});
}
Now here is some of the console output with the invalid dates:
a.cells[2].innerHTML = 28/11/2017 1:49:37 PM
b.cells[2].innerHTML = 5/09/2017 6:27:35 AM
a = Invalid Date
b = Tue May 09 2017 06:27:35 GMT+0930 (Cen. Australia Standard Time)
a.cells[2].innerHTML = 28/11/2017 1:49:37 PM
b.cells[2].innerHTML = 24/09/2017 6:12:48 PM
a = Invalid Date
b = Invalid Date
Does anyone know why this might be happening? It's got me stumped.
Date.parse uses RFC 2822 formatting and doesn't allow to specify a custom format. Though, if your input is consistently in the DD/MM/YYYY h:m:s AM/PM format, then you can use split to do the parsing yourself and manually create a Date object.
parseDate(a.cells[2].innerHTML);
parseDate(b.cells[2].innerHTML);
function parseDate(str) {
// Split into date, time, and AM/PM
var parts = str.split(" ");
// Split and parse the day, month, and year
var date = parts[0].split("/");
var day = parseInt(date[0]);
var month = parseInt(date[1]) - 1;
var year = parseInt(date[2]);
// Split and parse the hours, minutes, and seconds
var time = parts[1].split(":");
var hour = parseInt(time[0]);
var minute = parseInt(time[1]);
var second = parseInt(time[2]);
// Add 12 hours to the time if it's in the afternoon
if (parts[2] == "PM") { hour += 12; }
// Build and return our Date object
return new Date(year, month, day, hour, minute, second);
}
As others have mentioned, you can also use Moment to make things easier.
I have written the following code and cannot figure out why it is not working in my Google Sheet:
function WEEKOF(myDay, myDate) {
var wkDate = new Date(myDate);
var StartDate = new Date();
StartDate.setDate(wkDate.getDate()-myDay);
return StartDate;
}
=WEEKOF(Weekday(A1), A1)
Cell A1 contains: 05/01/2016
Return: 7/26/2017
I'm expecting the return to be: 04/29/2016
Difference in Days,Hours,Minutes and Seconds
var adayinmilliseconds=24*60*60*1000;
var differenceBetweenTwoDatesInDays = Math.floor((date1.valueOf()-date2.valueOf())/adayinmilliseconds);
A Date Difference Function that output days, hours, minute and seconds. From the MDN Date objects are based on a time value that is the number of milliseconds since 1 January, 1970 UTC. The method of time() and valuOf() both provide us the the primitive value of dates ie the number of milliseconds from some date in the past. Yes, it can be quite a large number but in the end with a little simple arithmetic Math.floor(), /, % you end up with an easy calculation. You can change the output to an array or an object depending upon your requirements.
function calcTimeDifference(Start,End)
{
if(Start && End)
{
var second=1000;
var minute=60*second;
var hour=minute*60;
var day=hour*24;
var t1=new Date(Start).valueOf();
var t2=new Date(End).valueOf();
var d=t2-t1;
var days=Math.floor(d/day);
var hours=Math.floor(d%day/hour);
var minutes=Math.floor(d%day%hour/minute);
var seconds=Math.floor(d%day%hour%minute/second);
return 'dd:hh:mm:ss\n' + days + ':' + hours + ':' + minutes + ':' + seconds;
}
else
{
return 'Invalid Inputs';
}
}
I have been working on a script that dynamically creates a date/time value between two days. However I want to limit it as follows:
if appointment.status === "today": Set the range between now (start) and the end of the working day (end) i.e. today between time right now to 18:00
if appointment.status === "pending": Set the range from tomorrow (start) + 1 week (end) but keeping in mind the working day i.e. 08:00-17:00... so it can be next week Tuesday 13:00
Once done, I would like to convert var date to a timestamp.
This is my code so far:
if (appointment.status === "today") {
appointment.timestamp = (function() {
var a = randomTime(new Date("10-10-2015 10:30"), new Date("12-10-2015 02:10"));
return a
})();
} else if (appointment.status === "pending") {
appointment.timestamp = (function() {
var a = randomTime(new Date("10-10-2015 10:30"), new Date("12-10-2015 02:10"));
return a
})();
}
function randomTime(start, end) {
var diff = end.getTime() - start.getTime();
var new_diff = diff * Math.random();
var date = new Date(start.getTime() + new_diff);
return date;
}
var start = new Date();
var end = new Date();
if (appointment.status === "today") {
end.setHours(18);
end.setMinutes(0);
} else if (appointment.status === "pending") {
start.setDate(start.getDate() + 1);
end.setDate(end.getDate() + 7);
}
start = restrictTimeToWorkHours(start);
end = restrictTimeToWorkHours(end);
appointment.timestamp = Math.floor(randomTime(start, end) / 1000);
function randomTime(start, end) {
var diff = end.getTime() - start.getTime();
var new_diff = diff * Math.random();
return new Date(start.getTime() + new_diff);
}
function restrictTimeToWorkHours(date) {
if (date.getHours() < 8) {
date.setHours(8);
date.setMinutes(0);
}
if (date.getHours() > 16) {
date.setHours(16);
date.setMinutes(0);
}
return date;
}
The key thing to remember here is the Math.floor(randomTime(start, end) / 1000);. You said you wanted it in timestamp, so I take it to mean you want a Unix Timestamp. A Unix Timestasmp is in seconds, while Date.getTime() is in milliseconds, so we need to divide by 1000 to get seconds
Either look for a date library or create your own date transformation function for each operation and combine those.
endOfDay(time)
getRandomTimeBetween(startTime, endOfDay(startTime))
isWorkingDay(time)
// etc.
For the second case, you can do it in two steps: select a random day in the range, then select a random time within the working hours of that day.
Break it down to simple, logical operations, and you can test each function separately, and your code will look nice and readable.
I am trying to compare two dates which are in Finnish time form like this: dd.mm.YYYY or d.m.YYYY or dd.m.YYYY or d.mm.YYYY.
I am having a hard time finding out how to do this, my current code won't work.
<script src="inc/date-fi-FI.js" type="text/javascript"></script>
<script type="text/javascript">
function parseDate() {
var date = $('#date').val();
var parsedDate = Date.parse(date);
alert('Parsed date: '+parsedDate);
}
function jämförMedIdag (datum) {
if (datum == null || datum == "") {
alert('Inget datum!');
return;
}
/*resultat = Date.compare(Datum1,Datum2);
alert(resultat); */
var datum = Date.parse(datum);
var dagar = datum.getDate();
var månader = datum.getMonth();
var år = datum.getYear();
var nyttDatum = new Date();
nyttDatum.setFullYear(år,månader,dagar);
var idag = new Date();
if(nyttDatum>idag) {
var svar = nyttDatum - idag;
svar = svar.toString("dd.MM.yyyy");
alert(svar);
return(svar);
} else {
var svar = idag - nyttDatum;
svar = svar.toString("dd.MM.yyyy");
alert(svar);
return(svar);
}
}
</script>
This code will try to calculate the difference between two dates, one of them being today. No success lolz.
Thanks in advance!
My final code (thanks RobG!):
function dateDiff(a,b,format) {
var milliseconds = toDate(a) - toDate(b);
var days = milliseconds / 86400000;
var hours = milliseconds / 3600000;
var weeks = milliseconds / 604800000;
var months = milliseconds / 2628000000;
var years = milliseconds / 31557600000;
if (format == "h") {
return Math.round(hours);
}
if (format == "d") {
return Math.round(days);
}
if (format == "w") {
return Math.round(weeks);
}
if (format == "m") {
return Math.round(months);
}
if (format == "y") {
return Math.round(years);
}
}
It is not fully accurate, but very close. I ended up adding some addons to it to calculate in day week month year or hour, anyone can freely copy and use this code.
If you are using Datejs, and the optional time.js module, you can run your calculations with the following code by creating a TimeSpan object:
Example
// dd.mm.YYYY or d.m.YYYY
// dd.m.YYYY or d.mm.YYYY
var start = Date.parse("20.09.2011");
var end = Date.parse("28.09.2011");
var span = new TimeSpan(end - start);
span.days; // 8
Of course the above could be simplified down to one line if you really want to be extra terse.
Example
new TimeSpan(Date.parse(end) - Date.parse(start)).days; // pass 'end' and 'start' as strings
Hope this helps.
If your dates are strings in the common form d/m/y or some variation thereof, you can use:
function toDate(s) {
var s = s.split('/');
return new Date(s[2], --s[1], s[0]);
}
You may want to validate the input, or not, depending on how confident you are in the consistency of the supplied data.
Edit to answer comments
To permit different separators (e.g. period (.) or hyphen (-)), the regular expression to split on can be:
var s = s.split(/[/\.-]/);
The date will be split into date, month and year numbers respectively. The parts are passed to the Date constructor to create a local date object for that date. Since javascript months are zero indexed (January is 0, February is 1 and so on) the month number must be reduced by one, hence --s[1].
/Edit
To compare two date objects (i.e get the difference in milliseconds) simply subtract one from the other. If you want the result in days, then divide by the number of milliseconds in a day and round (to allow for any minor differences caused by daylight saving).
So if you want to see how many days are between today and a date, use:
function diffToToday(s) {
var today = new Date();
today.setHours(0,0,0);
return Math.round((toDate(s) - today) / 8.64e7);
}
alert(diffToToday('2/8/2011')); // -1
alert(diffToToday('2/8/2012')); // 365
PS. The "Finnish" data format is the one used by the vast majority of the world that don't use ISO format dates.
Using the Date object:
var today = Date.today();
var dateToday = Date.parse(today.toString('MMMM d, yyyy'));
var prevMonthDate = dateToday.addDays(-30);
var difference = (dateToday - prevMonthDate)/86400000;
console.log(difference); //will give you the difference in days.