How to convert seconds into human readable time lapse - node.js

I have this function
const performance = require('perf_hooks');
var t0 = performance.now();
setInterval(printStatus, 20000);
function printStatus() {
console.log(
`Total records: ${count}`
);
console.log("Time elapsed" + (performance.now() - t0)/60000 + "minutes")
}
This prints minutes like this:
Time elapsed0.3334145895500978minutes
I want it to become human readable HH:MM:S
How do I make it happen?

I would do this:
const performance = require('perf_hooks');
var t0 = performance.now();
setInterval(printStatus, 20000);
function printStatus() {
console.log(
`Total records: ${count}`
);
const msElapsed = (performance.now() - t0);
const hhmmss = (new Date(msElapsed)).toISOString().substr(11,8);
console.log("Time elapsed " + hhmmss )
}

Related

Calculate difference between two timestamps

I'm using the twitch api and TMI.JS
I'm trying to fetch the timestamp of followed_at. The timestamp I got was 2021-12-25T15:49:57Z, how would I go about getting the current timestamp, and then calculating the difference. So in this instance it would return followername has been following streamername for 20 days 19 hours (at the time of writing it's been 20 days and 19 hours since the followed_at timestamp.)
if (message.toLowerCase() === '!followage') {
client.say(channel, `#${tags.username}, does not work yet `)
console.log(`${channel.id}`)
console.log(`${tags['user-id']}`)
async function getData() {
const res = await fetch(`https://api.twitch.tv/helix/users/follows?to_id=226395001&from_id=${tags['user-id']}`, { method: 'get', headers: {
'Client-Id': 'cut out for a reason',
'Authorization': 'Bearer cut out for a reason'
}});
const data = await res.json();
console.log(data)
if (data.data[0]) {
client.say(channel, `#${tags.username}, followed at ${data.data[0].followed_at}`)
} else {
client.say(channel, `You aren't followed!`)
}
}
getData()
}
Above is my code for fetching it, and then sending it to the channel.
Here's how you can do it:
const followedAt = new Date('2021-12-25T15:49:57Z');
const currentDate = new Date();
const diffTime = Math.abs(currentDate - followedAt);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
console.log(diffTime + " milliseconds");
console.log(diffDays + " days");
And that's the way to get days and hours:
const followedAt = new Date('2021-12-25T15:49:57Z');
const currentDate = new Date();
const diffTime = Math.abs(currentDate - followedAt);
const diffTotalHours = Math.floor(diffTime / (1000 * 60 * 60));
const diffDays = Math.floor(diffTotalHours / 24);
const diffHoursWithoutDays = diffTotalHours % 24;
console.log(`${diffDays} days and ${diffHoursWithoutDays} hours`);

Converting process.hrtime() to milliseconds

I have existing code that does the following use of hrtime
before = process.hrtime()
// stuff happens...
after = process.hrtime(before)
latency = (after[0] * 1000000000 + after[1]) / 1000000;
What unit is latency above?
Turns out the above is in fact milliseconds. Since setTimeout takes the delay value in milliseconds, it's easy to validate my hrtime juggling:
const times = []
const delays = [1, 10, 100, 1000, 1001, 1100];
function sleep(ms) {
return new Promise((res) => {
setTimeout(res, ms);
});
}
async function main() {
for (let ms of delays) {
const ping = process.hrtime();
await sleep(ms);
const pong = process.hrtime(ping);
const latency = (pong[0] * 1000000000 + pong[1]) / 1000000;
times.push(latency);
}
console.log(times);
// >>> [2.031091, 11.623596, 101.971041, 1000.554953, 1001.192077, 1104.29338]
}
main();

MongoDB aggregation returns empty array with NodeJS

I want to create a script which is taking the average of the Volume for last 7(for example) days.
I'm stuck with aggregation stages since first stage I need to take Date for last 7 days and in second stage calculate Average of Volume
Package list:
Node-schedule - */1 * * * * (Runs the script every minute)
Binance API - Taking data from them.
Screenshot for showcasing how the document looks like in MongoDB.
Aggregation part of the Code.
const average = await dbo.collection(symbol).aggregate([{
'$match': {
'Date': { '$gte': new Date((new Date().getTime() - (7 * 24 * 60 * 60 * 1000))) }
},
},
{
'$group': {
_id: null,
'Volume': { '$avg': '$Volume' }
},
}
]).toArray();
This code returns me an empty array in terminal like this > []
Full Code here.
const { MongoClient } = require('mongodb');
const schedule = require('node-schedule');
const fetch = require("node-fetch");
const symbols = ["ADABTC", "AEBTC", "AIONBTC", "ALGOBTC", "ARDRBTC"];
//a descriptive name helps your future self and others understand code easier
const getBTCData = async symbol => { //make this function accept the current symbol
//async/await lets us write this much nicer and with less nested indents
let data = await fetch(`https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=30m&limit=1`).then(res => res.json());
const btcusdtdata = data.map(d => {
return {
Open: parseFloat(d[1]),
High: parseFloat(d[2]),
Low: parseFloat(d[3]),
Close: parseFloat(d[4]),
Volume: parseFloat(d[5]),
Timespan: 30,
}
});
console.log(btcusdtdata);
saveToDatebase(symbol, btcusdtdata);
//recursive functions are complicated, we can get rid of it here
//by moving the responsibility to the caller
};
//helper function for an awaitable timeout
const sleep = ms => new Promise(res => setTimeout(res, ms));
const j = schedule.scheduleJob('*/1 * * * *', async() => {
//expand this function to be responsible for looping the data
for (let symbol of symbols) {
//we can pass symbol to getBTCData instead of making it
//responsible for figuring out which symbol it should get
await getBTCData(symbol);
await sleep(8000);
}
});
//make this a helper function so `saveToDatabase()` isn't also responsible for it
const getDateTime = () => {
let today = new Date();
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return date + ' ' + time;
};
const saveToDatebase = async(symbol, BTCdata) => {
try {
const url = 'mongodb://username:password#ipadress:port/dbname';
let dateTime = getDateTime();
let db = await MongoClient.connect(url, { useUnifiedTopology: true });
const dbo = db.db('Crypto');
const myobj = Object.assign({ Name: symbol, Date: dateTime }, BTCdata[0]);
await dbo.collection(symbol).insertOne(myobj);
const average = await dbo.collection(symbol).aggregate([{
'$match': {
'Date': { '$gte': new Date((new Date().getTime() - (7 * 24 * 60 * 60 * 1000))) }
},
},
{
'$group': {
_id: null,
'Volume': { '$avg': '$Volume' }
},
}
]).toArray();
console.log('1 document inserted');
console.log(average);
db.close();
} catch (e) {
console.error(e)
}
};
EDIT1
If I delete $match part my script is working and I receive average of Volume.
Screenshot of terminal after success try without $match
EDIT2
According to the last answer I understand that I need to change Date format from string to object, but I really can't get how I can do it in this part?
const getDateTime = () => {
let today = new Date();
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return date + ' ' + time;
};
EDIT3
After editing the Date format I receive a Document in MongoDB in strange Date format like - Date:2020-07-20T13:24:02.390+00:00
Code here:
const getDateTime = () => {
let today = new Date();
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return new Date();
};
The problem is on the Date field format.
The getDateTime function returns a string so Mongo is managing the field as a string not as a Date object so the $gte check will compare string not dates.
You should change the function to getDateTime = () => new Date(). Mongo will manage the date correctly storing in UTF Timezone.
Tring to query a date-string in the $match field would be really difficult.
Edit:
To update the typing just:
const getDateTime = () => {
return new Date();
};

setTimeout() function is not executed properly

I have to send an SMS 15 minutes before the appointment is there. I have written the code, but it is called at the time of execution itself. Is there any other method or how do I solve this?
"RP.remindePatient" is the function that has to be called 15 minutes before the appointment time.
sendApptConf(s) {
var number = Phone;
var msg = urlencode("Hello " );
var smsData = 'username=' + username + '&hash=' + hash + '&sender=' + sender + '&numbers=' + number + '&message=' + msg;
var options = {
host: 'api.textlocal.in',
path: '/send?' + smsData
};
var callback;
console.log(options);
callback = function (response) {
var str = '';
// Another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
console.log("new Data received")
str += chunk;
console.log(str);
});
// The whole response has been received, so we just print it out here.
response.on('end', function () {
console.log(str);
});
}
http.request(options, callback).end();
// Send SMS using Textlocal DONE
const convertTime = consultDate + ' ' + consultTime;
var d = new Date(convertTime);
var ms = d.getTime();
var milliLess15 = ms - (15 * 60 * 1000);
console.log(milliLess15);
setTimeout(function () {
console.log("I should be called after some delay")
RP.remindePatient(userPhone, patientName, drName, consultMode, consultDate, consultTime, transId, email, paymentDetails);
}, milliLess15);
I think there is a small issue in your logic. As you would already know, setTimeout(function () {}, milliseconds) will fork the function() after milliseconds you have specified.
Now let's focus on the below snippet of code:
const convertTime = consultDate + ' ' + consultTime;
var d = new Date(convertTime);
var ms = d.getTime();
var milliLess15 = ms - (15 * 60 * 1000);
Let's say your appointment is at 12:00 pm today (in millisec let's say 1492776423) and current execution time is 10:00 am (in millisec 1485576423). By your logic, you are calling the function() after: var milliLess15 = ms - (15 * 60 * 1000) which is 1492776423 - (15 * 60 * 1000) = 1491876423. Note here that, you don't want to call function() after 1491876423 millisec. Rather you want to call it after millisec equivalent of 12:00 - 10:00 - 00:15. So your logic should look something like:
const convertTime = consultDate + ' ' + consultTime;
var d = new Date(convertTime);
var ms = d.getTime();
var currentTime = new Date();
var currentTimeMilli = currentTime.getTime();
var milliLess15 = ms - (15 * 60 * 1000) - currentTimeMilli;
Rest of the code will remain the same. Hope this answer helps you!
Don't call the variable after timeout. Just put in:
setTimeout(function () {
console.log("I should be called after some delay")
RP.remindePatient(userPhone, patientName, drName, consultMode, consultDate, consultTime, transId, email, paymentDetails);
}, 900000);

how to use process.hrtime to get execution time of async function

I am triing to get execution time of async function. Seemingly I can use process.hrtime for this. I created simple example:
console.log("starting");
var start = process.hrtime();
console.log("start");
console.log(start);
setTimeout(function(){
console.log("HELLO");
var end = process.hrtime();
console.log("end");
console.log(end);
}, 1000);
It outputs
starting
start
[ 131806, 731009597 ]
HELLO
end
[ 131807, 738212296 ]
But I don't understand where is exectuion time in miliseconds? I expect to get 1000 ms in this example.
Got it:
console.log("starting");
var start = process.hrtime();
console.log("start");
console.log(start);
setTimeout(function(){
console.log("HELLO");
var end = process.hrtime(start);
console.log("end");
console.log(end);
}, 1000);
Prints
starting
start
[ 132798, 207101051 ]
HELLO
end
[ 1, 7001730 ]
That means 1 second and 7001730 nanoseconds from start to end
Since Node 10.7.0, process.hrtime is marked as 'legacy', with the recommended method being process.hrtime.bigint. The documentation contains an example of how to use this method to time an operation:
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);
Just to add in case someone needs the execution time in ms:
console.log("starting");
var start = process.hrtime();
console.log("start");
console.log(start);
setTimeout(function(){
console.log("HELLO");
var end = process.hrtime(start); // end[0] is in seconds, end[1] is in nanoseconds
const timeInMs = (end[0]* 1000000000 + end[1]) / 1000000; // convert first to ns then to ms
console.log("timeInMs:", timeInMs);
}, 1000);
Here's a simple wrapper timing function for async functions:
// async function execution time wrapper
async function fnTime(fn, ...params) {
const start = process.hrtime()
const result = await fn(...params)
const end = process.hrtime(start)
console.log(
`[${fn.name}] Execution time:${(end[0] * 1000000000 + end[1]) /
1000000} ms`
)
return result
}
example usage (see this demo on repl.it):
// usage
const setTimeoutPromise = ms => new Promise(resolve => setTimeout(resolve, ms))
// example 2:
// get name from db
const db = {
async getUser(id){
// simulate wait for record retrival from db
await fnTime(setTimeoutPromise, 150)
return {
_id: id,
name: 'John Doe',
organisation: 'UN',
email: 'johndoe#un.org'
}
}
}
// test it
;(async function(){
const result = await fnTime(db.getUser, 'asfa98th4nfwef0qwrwef0')
console.log('result', result)
})()
// result:
// [setTimeoutPromise] Execution time:197.928094 ms
// [getUser] Execution time:199.480553 ms

Resources