Thanks for opening my question. What I'm doing, to me, should be very simple. I am a beginner for programming so I am not aware of what I need to get this done. I need help.
The problem:
I have to have 4 columns for times. (Travelto, Arrive, Depart, Travelfrom) I don't always use all of them so my script has to recognize that I want certain values based on which cells in a row are blank or which have content. I have tried using isblank() on the spreadsheet to determine a binary number which I then convert to a decimal. I'd like my script to do that so I don't have to add another column to my google sheets. I think I would use an array and then check if each element is blank in the array then multiply each element in that array by 1 so it's now a number instead of a boolean. Then I want to take the elements of the array and convert them into a single binary number and convert that to a decimal number to feed to my switch case, which will contain the correct way to calculate the hours and return the hours in decimal so it should be formated such as 1.75 for 1 hr 45 mins. The value it returns must be able to be summed so the function can't return a string. also I prefer 2 decimal places for the output.
I have attempted to figure out how to calculate the time in google's apps Script. I have had limited success. The output of my script is unintelligible as to how it got the answer it did. This is probably because I can't figure out how to tell what the script sees the times as. does it see 13:00:00, 0.5416667, or something completely different? I can't seem to figure it out.
I want to pass two values from a google sheets spreadsheet, which are visually formatted as time, then take those two times subtract one from the other and get the amount of time between them, the duration so that I know how many hours have been worked.
function worked(time1,time2) //pass 2 time values to function
{ //Start of the function
var time1; //declare time1 variable
var time2; //Declare time 2 variable
var outnumber = time1-time2; //Declare outnumber and subtract time1 from time2
return outnumber //return the difference of time1 and time2
}
here's the link to my sheet and code included in the editor. anyone with the link can comment
https://docs.google.com/spreadsheet/ccc?key=0Ar4A89ZoxmJCdHBFR0VCblVtWUVvR3hFbTdlcjdKNUE&usp=sharing
Please tell me what I'm doing wrong or not doing at all to make this work.
Thanks
Goldenvocals369
The number you are seeing outputted is the difference in ms. You need to convert ms to the format you want.
I found a neat way to do that here: https://coderwall.com/p/wkdefg
Your code would look like this.
function worked(time1,time2)
{
var time1;
var time2;
var outnumber = time1-time2;
return msToTime(outnumber)
}
function msToTime(duration) {
var milliseconds = parseInt((duration%1000)/100)
, seconds = parseInt((duration/1000)%60)
, minutes = parseInt((duration/(1000*60))%60)
, hours = parseInt((duration/(1000*60*60))%24);
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return hours + ":" + minutes + ":" + seconds;
}
You can use this function. The function's documentation is:
Returns the displayed value of the top-left cell in the range. The
value will be of type String. The displayed value takes into account
date, time and currency formatting formatting, including formats
applied automatically by the spreadsheet's locale setting. Empty cells
will return an empty string.
Related
I have this webpage that takes in an input in seconds, and produces what the time will be after the time has elapsed. So I went about it using the following code
let duration = prompt("Enter your trip duration in seconds: "); // get the time from the vaue of the input element
let newtime = new Date(); // get the current time
newtime.setSeconds(newtime.getSeconds() + duration)
I decided to test the code and it gave me weird results and for some reason when I divided the duration by ten it started to work. Even though it worked I wasn't satisfied. So I added some more code to try and find where the bug is.
let oldtime = new Date();
oldtime.setSeconds(oldtime.getSeconds() + 60);
I added some code so that it would show on the webpage to compare the two times and these are my results when I enter 60 as the duration...
Just a little summary. The code works when I hard code the values in but it behaves weirdly if I try get the input from a prompt
You are concatenating a string to a number instead of adding. You have to parse the result from prompt to a number (with the unary plus operator):
let duration = prompt("Enter your trip duration in seconds: "); // get the time from the vaue of the input element
let newtime = new Date(); // get the current time
newtime.setSeconds(newtime.getSeconds() + +duration)
console.log(newtime)
I believe the issue is because you need to parse the duration from a string to number. So, try this
newtime.setSeconds(newtime.getSeconds() + parseInt(duration, 10))
You can use a library like Luxon to deal with dates and times without having to worry about unexpected behaviour like the one you described.
import { DateTime } from "luxon";
const now = DateTime.now();
const timeAfterTrip.plus({ seconds: duration });
console.log(timeAfterTrip);
First, I give thanks to ksav and his help thus far.
I'm a foreman for a landscaping company and it's my responsibility to fill out forms for each site and keep track of our man hours so we don't go over the allotted time. I'm trying to digitize the documents in Adobe so I can enter the times in the field on my phone without pen and paper and have a JavaScript code automatically calculate the hours on site in decimal format.
Note: I will be using 24-hour time aka military time (13:00/1PM 16:40/4:40PM)
The JS code currently used within Adobe isn't calculating/converting the time difference correctly:
This gives incorrect decimal calculations on the time difference:
var start = this.getField("Monday Site #1 Start Time").value;
var startArr = start.split(":");
// finish
var finish = this.getField("Monday Site #1 Depart Time").value;
var finishArr = finish.split(":");
// difference
var hourDiff = Math.abs(finishArr[0] - startArr[0]);
var minDiff = Math.floor((Math.abs(finishArr[1] - startArr[1]) / 59)*100);
if (minDiff.toString().length == 1)
minDiff = '0' + minDiff;
var output = hourDiff + "." + minDiff;
event.value = output;
if ((event.value == "") || (event.value == Infinity) || isNaN(event.value))
{event.value = "";}
Examples of the hour-decimal calculation errors:
I should mention these fields are all uniquely named Form Fill fields within Adobe, hence the variable field names "Monday Site #1 Start Time, Monday Site #1 Depart Time, MS1 Total Hours etc etc:
See my original question where I tried other JS code to no avail. Some of those snippets didn't give me any value whatsoever
I have limited knowledge on JavaScript code so any assistance with this would be greatly appreciated!
I'm running into an issue where my app is being accessed from different parts of the world. And, I have a chart to display peak access times. If accessed from a different part of the world (than the origin) I need it to reflect the converted origin time. However, the way it is currently set up, the calculation renders fooPoint.hour with the value of for example 28 instead of 00:03 (am).
I can pinpoint that this occurs in the else conditional, since, for example, if they would be Accessing from Australia, with a fooPoint.hour = 20 and this.state.timeZoneOffset = -8. 20 - (-8) = 28 and I would like it to display as 00:04. I know my calculations are wrong, so can anyone help me format this correctly please?
I failed to mention that fooPoint.hour is actually a data point I get in the foo object (which is fetched from an API), so that represents the avg. peak time of certain location. When viewed from another location in a different part of the world, I need to take into account the time zone difference to display in the chart the peak time but on their time zone
Is a library a low technical debt solution?
I have this array of objects as such:
foo: {
hour: 20
}
I obtain the timezone offset as such:
let tzOffset = new Date().getTimezoneOffset() / 60;
and store it in state
Then I have:
foo.forEach((fooPoint) => {
fooPoint.hour =
fooPoint.hour - this.state.timeZoneOffset < 0
? fooPoint.hour - this.state.timeZoneOffset + 24
: foorPoint.hour - this.state.timeZoneOffset;
});
So you have two possible conditions that you want to fix:
The timezone offset takes an early morning time and produces a negative result. I believe that your code will handle that.
The timezone offset takes a late evening result and makes it higher than 24. Your code is missing this adjustment.
Try
foo.forEach((fooPoint) => {
fooPoint.hour -= this.state.timeZoneOffset;
fooPoint.hour =
fooPoint.hour < 0
? fooPoint.hour + 24
: foorPoint.hour >= 24
? fooPoint.hour - 24
: fooPoint.hour;
});
Moving the subtraction out is just because I'm lazy and don't want to repeat it five times.
The critical part here is to test for both possibilities.
You might also find it more readable as if statements.
foo.forEach((fooPoint) => {
fooPoint.hour -= this.state.timeZoneOffset;
if (fooPoint.hour < 0) {
fooPoint.hour += 24;
} else if (fooPoint.hour >= 24) {
fooPoint.hour -= 24;
}
});
The two are functionally the same, but many would find that easier to follow.
I've got a stopwatch app that stores the times in an array. The JS counts milliseconds from when the timer is started, then converts those milliseconds into seconds and minutes, and outputs that as a string.
What I'm trying to do is calculate the averages of these times, so I have to convert the strings into floats. It can convert a string like 10.35 to a float just fine, but it obviously doesn't work with something like 1:24.56, that's what I'm trying to fix. The time will be in one of these formats:
[seconds].[milliseconds]
[minutes]:[seonds].[milliseconds]
Any ideas? I'm really new with Javascript so I'm not sure where to go with this.
EDIT: The repo is here. All of the nonsense happens in the timer.js and main.js files.
Just split it, and add it up:
function toMS(str) {
if(!str.includes(":"))
return parseFloat(str);
const [mins, secms] = str.split(":");
const [sec, ms] = secms.split(".");
return ((+mins * 60) + +sec) * 1000 + +ms;
}
(This uses "unary plus operators" to convert the strings into numbers)
I have a strange timezone/date formatting issue that recently came up with some new code, and what makes it more strange is that it only affects two months - August and September.
The code takes a date string with UTC time formatted like this:
10-06-2017 09:29:15
And converts it to a new string with the same format but with local time. The zeroPad function ensures that the format remains the same.
We implemented it in March and everything worked fine. It's within Classic ASP on IIS9/Server 2012.
As soon as we got to August, it broke. 08-10-2017 09:33:06 becomes 12-09-2016 20:33:06.
Can anyone see what I've done wrong?
function jsConvert(dateString) {
var patterns = dateString.split(/[\-\s:]/g);
var date = new Date(parseInt(patterns[2]),
parseInt(patterns[0]) - 1,
parseInt(patterns[1]),
parseInt(patterns[3]),
parseInt(patterns[4]),
parseInt(patterns[5]));
date.setTime(date.getTime() - getTimezoneOffset() * 60 * 1000);
var result = zeroPad(date.getMonth() + 1);
result += '-' + zeroPad(date.getDate());
result += '-' + date.getFullYear();
result += ' ' + zeroPad(date.getHours());
result += ':' + zeroPad(date.getMinutes());
result += ':' + zeroPad(date.getSeconds());
return result;
}
function zeroPad(number) {
return (number < 10) ? '0' + number : number;
}
What are the units of time in your getTimezoneOffset() function?
Your code is written as though the getTimezoneOffset() function returns a number of minutes, since you are multiplying by 60 and then 1000, to get millseconds.
But if your getTimezoneOffset is returning seconds, you will be over-doing the multiplication and therefore jumping back too far in time.
I think it would have to be milliseconds, to jump back the distance you are getting. #CBroe above mentions that perhaps you mean the builtin getTimezoneOffset function, which is indeed in minutes. Perhaps you have a separate getTimezoneOffset function defined in your code elsewhere, that returns an answer in milliseconds? In which case CBroe's answer fixes it.
My next suggestion would be to add lines of debugging code
For example, could you add the following?
At the beginning, add console.log("A",dateString).
After var patterns = dateString.split(/[\-\s:]/g); add a line console.log("B",patterns);.
After var date = ...(patterns[5])); add a line console.log("C",date);.
After date.setTime...1000); add a line console.log("D",date); console.log("E",getTimezoneOffset());.
If you show us the output of these lines, we should be able to pinpoint the problem easily. I have included item E because I am just wondering if there is yet another getTimezoneOffset() function in your system, which we are not aware of, or something. Seeing its value will help reassure everyone.
Meanwhile can you confirm the time zone you are running the code in? I am guessing it is in the USA rather than Europe, from your preference for putting month before the day?
So as it turns out this is a known, albeit obscure issue. It has to do with the fact that parseInt assumes that numbers with leading zeros are NOT base 10, but instead radix. It's well documented here: Javascript parseInt() with leading zeros
Once I made the change to:
parseInt(patterns[2]**, 10**);
All was good.
Thanks for the input.