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)
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);
I need to get unique random number in javascript (or Typescript).
At this moment I use this code:
var id = -((new Date()).getTime() & 0xffff);
It returns me numbers like -13915 or -28806 ...
It works most of the time but I am having problems when this code is executed in promises (so nearly multiple times at the same time). Then sometimes I got two identical id.
Is there any solution to get unique random numbers in any case ?
There are many examples around internet. You can start with using Math.random()
. For example: generate random number between 1 and 100
Math.floor((Math.random() * 100) + 1);
Just keep in mind that it is not truly random; it is not cryptographically secure. You should probably look into libraries if you need that
Create a function that returns a unique number:
let numbers = [];
const uniqueNumber = (maxVal) => {
const number = Math.floor((Math.random() * maxVal) + 1);
if (!numbers.includes(number)) {
numbers.push(number);
return number;
} else if (numbers.length - 1 !== maxVal) {
uniqueNumber(maxVal);
}
}
const randomNumber = uniqueNumber(100);
console.log(numbers) // returns all unique numbers
This will return a unqiue number between 1 and 100. It also stops at the max length.
You can use the package uuid:
const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
Notice: It is a number (a 128-bit number) but it is too big to be used as a JavaScript number. You have to keep it as a string.
If you need it on the browser, I suggest to generate the identifier from an API exposed on your back-end. Implementations of UUID exist in most of languages. The npm package will work on browsers but then it uses a fallback to Math.random, which is not secure.
See also: Universally unique identifier.
var datetimestamp = Date.now() + Math.random().toString(36).substr(2, 9);
Math.random() in itself should be safe enough, what with 64-bit numbers. Even with imperfect generator, the chances of hitting the same number twice are minuscule.
If you're after specifically integers, then multiply Math.random() by something BIG, like Number.MAX_SAFE_INTEGER.
To be perfectly safe, you can always store an array of already used ids, and write a function that draws as long as gets a new unique number, pushes it into array, and returns the value. Enclose all that functionality inside a single object/function/class, to keep it neat.
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.
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.
How can I get the most accurate time stamp in Node.js?
ps My version of Node.js is 0.8.X and the node-microtime extension doesn't work for me (crash on install)
In Node.js, "high resolution time" is made available via process.hrtime. It returns a array with first element the time in seconds, and second element the remaining nanoseconds.
To get current time in microseconds, do the following:
var hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
(Thanks to itaifrenkel for pointing out an error in the conversion above.)
In modern browsers, time with microsecond precision is available as performance.now. See https://developer.mozilla.org/en-US/docs/Web/API/Performance/now for documentation.
I've made an implementation of this function for Node.js, based on process.hrtime, which is relatively difficult to use if your solely want to compute time differential between two points in a program. See http://npmjs.org/package/performance-now . Per the spec, this function reports time in milliseconds, but it's a float with sub-millisecond precision.
In Version 2.0 of this module, the reported milliseconds are relative to when the node process was started (Date.now() - (process.uptime() * 1000)). You need to add that to the result if you want a timestamp similar to Date.now(). Also note that you should bever recompute Date.now() - (process.uptime() * 1000). Both Date.now and process.uptime are highly unreliable for precise measurements.
To get current time in microseconds, you can use something like this.
var loadTimeInMS = Date.now()
var performanceNow = require("performance-now")
console.log((loadTimeInMS + performanceNow()) * 1000)
See also: Does JavaScript provide a high resolution timer?
node v10 and later: you should be using process.hrtime.bigint(), which yields a single BigInt number rather than an array. process.hrtime() has been marked "legacy"
Older than node v10: As stated by vaughan, process.hrtime() is available within Node.js - its resolution are nanoseconds and therefore its much higher. This function returns an array [seconds, nanoseconds] containing the current real-time high-resolution value, but note that it is not tied to any specific clock, meaning the difference in two successive values tells you how much time passed, but individual values tell you nothing meaningful.
Other JS environments: new Date().getTime()? This gives you a timestamp in milliseconds.
Update:
now('milli'); // 120335360.999686
now('micro') ; // 120335360966.583
now('nano') ; // 120335360904333
Known that now is :
const now = (unit) => {
const hrTime = process.hrtime();
switch (unit) {
case 'milli':
return hrTime[0] * 1000 + hrTime[1] / 1000000;
case 'micro':
return hrTime[0] * 1000000 + hrTime[1] / 1000;
case 'nano':
default:
return hrTime[0] * 1000000000 + hrTime[1];
}
};
The BigInt data type is supported since Node.js 10.7.0. (see also the blog post announcement). For these supported versions of Node.js, the process.hrtime([time]) method is now regarded as 'legacy', replaced by the process.hrtime.bigint() method.
The bigint version of the process.hrtime() method returning the current high-resolution real time in a bigint.
const start = process.hrtime.bigint();
// 191051479007711n
setTimeout(() => {
const end = process.hrtime.bigint();
// 191052633396993n
console.log(`Benchmark took ${end - start} nanoseconds`);
// Benchmark took 1154389282 nanoseconds
}, 1000);
tl;dr
Node.js 10.7.0+ - Use process.hrtime.bigint()
Otherwise - Use process.hrtime()
There's also https://github.com/wadey/node-microtime:
> var microtime = require('microtime')
> microtime.now()
1297448895297028
You can also use performance API that works both in NodeJS and Browser:
var start = performance.timing ?
performance.timing.navigationStart :
performance.timeOrigin;
var time = (performance.now() + start) * 1000;
The Performance API stores value in floating-point number and the fraction is microseconds.
Node.js nanotimer
I wrote a wrapper library/object for node.js on top of the process.hrtime function call. It has useful functions, like timing synchronous and asynchronous tasks, specified in seconds, milliseconds, micro, or even nano, and follows the syntax of the built in javascript timer so as to be familiar.
Timer objects are also discrete, so you can have as many as you'd like, each with their own setTimeout or setInterval process running.
It's called nanotimer. Check it out!
To work with more precision than Date.now(), but with milliseconds in float precision:
function getTimeMSFloat() {
var hrtime = process.hrtime();
return ( hrtime[0] * 1000000 + hrtime[1] / 1000 ) / 1000;
}
The only way nowdays is call some 3rd party.
A lib with compiled function written on C (does't matter language, the point is OS syscall). Write your own or use for example https://www.npmjs.com/package/microtime (src https://github.com/wadey/node-microtime/blob/master/src/microtime.cc)
Spawn a process with date +%s%N, works on Linux out of box. Possible by using require('child_process').exec. I have no idea how accurate time would be because of performance of this solution
Note: process.hrtime is not about current time,
These times are relative to an arbitrary time in the past, and not related to the time of day.
[https://www.geeksforgeeks.org/node-js-process-hrtime-method/]
Edit:
Use jcubic's or Alexandr's answers below :
https://stackoverflow.com/a/69870775/2550964 https://stackoverflow.com/a/72741299/2550964
I'm not so proud about this solution but you can have timestamp in microsecond or nanosecond in this way:
const microsecond = () => Number(Date.now() + String(process.hrtime()[1]).slice(3,6))
const nanosecond = () => Number(Date.now() + String(process.hrtime()[1]).slice(3))
// usage
microsecond() // return 1586878008997591
nanosecond() // return 1586878009000645600
// Benchmark with 100 000 iterations
// Date.now: 7.758ms
// microsecond: 33.382ms
// nanosecond: 31.252ms
Know that:
This solution works exclusively with node.js,
This is about 3 to 10 times slower than Date.now()
Weirdly, it seems very accurate, hrTime seems to follow exactly js timestamp ticks.
You can replace Date.now() by Number(new Date()) to get timestamp in milliseconds
Edit:
Here a solution to have microsecond with comma, however, the number version will be rounded natively by javascript. So if you want the same format every time, you should use the String version of it.
const microsecondWithCommaString = () => (Date.now() + '.' + String(process.hrtime()[1]).slice(3,7))
const microsecondWithComma = () => Number(Date.now() + '.' + String(process.hrtime()[1]).slice(3,7))
microsecondWithCommaString() // return "1586883629984.8997"
microsecondWithComma() // return 1586883629985.966
A rewrite to help quick understanding:
const hrtime = process.hrtime(); // [0] is seconds, [1] is nanoseconds
let nanoSeconds = (hrtime[0] * 1e9) + hrtime[1]; // 1 second is 1e9 nano seconds
console.log('nanoSeconds: ' + nanoSeconds);
//nanoSeconds: 97760957504895
let microSeconds = parseInt(((hrtime[0] * 1e6) + (hrtime[1]) * 1e-3));
console.log('microSeconds: ' + microSeconds);
//microSeconds: 97760957504
let milliSeconds = parseInt(((hrtime[0] * 1e3) + (hrtime[1]) * 1e-6));
console.log('milliSeconds: ' + milliSeconds);
//milliSeconds: 97760957
Source: https://nodejs.org/api/process.html#process_process_hrtime_time
Get hrtime as single number in one line:
const begin = process.hrtime();
// ... Do the thing you want to measure
const nanoSeconds = process.hrtime(begin).reduce((sec, nano) => sec * 1e9 + nano)
Array.reduce, when given a single argument, will use the array's first element as the initial accumulator value. One could use 0 as the initial value and this would work as well, but why do the extra * 0.
there are npm packages that bind to the system gettimeofday() function,
which returns a microsecond precision timestamp on Linux. Search for
npm gettimeofday. Calling C is faster than process.hrtime()
process.hrtime() not give current ts.
This should work.
const loadNs = process.hrtime(),
loadMs = new Date().getTime(),
diffNs = process.hrtime(loadNs),
microSeconds = (loadMs * 1e6) + (diffNs[0] * 1e9) + diffNs[1]
console.log(microSeconds / 1e3)
better?
Number(process.hrtime().join(''))