Wrong hour difference between 2 timestamps (hh:mm:ss) - node.js

Using moment.js, I want to get the time difference between 2 timestamps.
Doing the following,
var prevTime = moment('23:01:53', "HH:mm:SS");
var nextTime = moment('23:01:56', "HH:mm:SS");
var duration = moment(nextTime.diff(prevTime)).format("HH:mm:SS");
I get this result :
01:00:03
Why do I have a 1 hour difference? seconds and minutes seem to work well.
After doing that, I tried the following :
function time_diff(t1, t2) {
var parts = t1.split(':');
var d1 = new Date(0, 0, 0, parts[0], parts[1], parts[2]);
parts = t2.split(':');
var d2 = new Date(new Date(0, 0, 0, parts[0], parts[1], parts[2]) - d1);
return (d2.getHours() + ':' + d2.getMinutes() + ':' + d2.getSeconds());
}
var diff = time_diff('23:01:53','23:01:56');
output is : 1:0:3

The problem you are having here is that when putting the nextTime.diff() in a moment constructor, you are effectively feeding milliseconds to moment() and it tries to interpret it as a timestamp, which is why you don't get the expected result.
There is no "nice way" of getting the result you want apart from getting a time and manually reconstructing what you are looking for :
var dur = moment.duration(nextTime.diff(prevTime));
var formattedDuration = dur.get("hours") +":"+ dur.get("minutes") +":"+ dur.get("seconds");
And a more elegant version that will give you zero padding in the output :
var difference = nextTime.diff(prevTime);
var dur = moment.duration(difference);
var zeroPaddedDuration = Math.floor(dur.asHours()) + moment.utc(difference).format(":mm:ss");
Should make you happier!
EDIT : I have noticed you use HH:mm:SS for your format, but you should instead use HH:mm:ss. 'SS' Will give you fractional values for the seconds between 0 and 999, which is not what you want here.

Related

Generating bulk dates

I wanted to ask if anyone knows a way of generating bulk dates. I want to know about how can I generate all of the dates and times between 20130631_0000 till 20151231_2359
The month limit is 0-12
The day limit is 0-31
and the part you see after underscore is hour and minute, the hour limit is 00 till 23 and the minute is from 00 till 59. It's basically YYYYMMDD_HHMM
Few examples:
20130810_1154, 20140103_2357, 20150722_1049, 20140103_2358, 20140103_2359, 20140104_0000, 20140104_0001, 20140105_1159, 20140105_1200
If you simply want to print each date to the console:
let date = new Date(2013,6,31,0,0);
const endDate = new Date(2015,12,31,23,59);
const padWithZero = num => num.toString().padStart(2, '0');
while (date <= endDate) {
const year = date.getFullYear();
const month = padWithZero(date.getMonth()+1);
const day = padWithZero(date.getDate());
const hour = padWithZero(date.getHours());
const minute = padWithZero(date.getMinutes());
console.log(`${year}${month}${day}_${hour}${minute}`)
date = new Date(date.getTime() + 60000)
}
Try this
function convertStringToDate(date){
var year = date.substring(0,4)
var month = date.substring(4,6)
var day = date.substring(6,8)
var hour = date.substring(9,11)
var minute = date.substring(11,13)
return new Date(parseInt(year), parseInt(month), parseInt(day), parseInt(hour), parseInt(minute) )
}
function addMinute(date){
var new_date = date;
new_date.setMinutes(date.getMinutes()+1)
return new_date
}
function getDatesBetween(start_date_str, end_date_str){
var start_date = convertStringToDate(start_date_str)
var end_date = convertStringToDate(end_date_str)
dates = []
date = start_date
while(date.getTime() !== end_date.getTime()){
dates.push(new Date(date))
date = addMinute(date)
}
dates.push(end_date)
return dates
}
function pad (str, max) {
str = str.toString();
return str.length < max ? pad("0" + str, max) : str;
}
function convertDateToString(date){
var year = date.getFullYear().toString()
var month = pad(date.getMonth().toString(),2)
var day = pad(date.getDay().toString(),2)
var hour = pad(date.getHours().toString(),2)
var minutes = pad(date.getMinutes().toString(),2)
return year + month + day + "_" + hour + minutes
}
var start_date_str = "20130620_1224"
var end_date_str = "20130621 1224"
dates = getDatesBetween(start_date_str, end_date_str)
formatted_dates = dates.map(convertDateToString)
console.log(dates.length)
console.log(dates[dates.length-1])
console.log(formatted_dates.length)
console.log(formatted_dates[dates.length-1])

Color console.log timestamps?

So, I'm using this code from 6 years ago and would like to color the timestamps however I don't know where to put the colors.
var log = console.log;
console.log = function () {
var first_parameter = arguments[0];
var other_parameters = Array.prototype.slice.call(arguments, 1);
function formatConsoleDate (date) {
var hour = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
return '[' +
((hour < 10) ? '0' + hour: hour) +
':' +
((minutes < 10) ? '0' + minutes: minutes) +
':' +
((seconds < 10) ? '0' + seconds: seconds) +
'] ';
}
log.apply(console, [formatConsoleDate(new Date()) + first_parameter].concat(other_parameters));
};
Any help would be appreciated.
Edit: I was able to color the timestamps without any modules or anything by putting a color at the END of every console.log, and it colors the next line. I would assume there is a better way to do this however.
console.log('\x1b[36m%s\x1b[0m', 'colored word',' \x1b[32m\x1b[0');That for example, would color the consoles timestamps green.
Check the article on the Node.js knowledgebase: How to get colors on the command line

Converting geo coordinates Format

i am asked to show a gps device on a google map. i have written a listener and the format looks something like this
1724.1543,N,07822.4276,E
how to convert these into degrees, minutes and seconds format like
17.241543,78.224276
Apparently google maps recognizes lat lng in the above format only.
My listener is written in nodejs, so a javascript way to convert is more appreciated.
thanks.
javascript way to convert lat and long to degree,minute and second is as follows:
//to convert pass lat or long to this function
function DECtoDMS(dd)
{
var vars = dd.split('.');
var deg = vars[0];
var tempma = "0."+vars[1];
tempma = tempma * 3600;
var min = Math.floor(tempma / 60);
var sec = tempma - (min * 60);
return deg+"-"+min+"-"+sec;
}
//call the function
var inDeg = DECtoDMS(72.8479400);
console.log(inDeg);

What is wrong with my code to calculate a standard deviation?

I'm trying to calculate the standard deviation of a set of numbers as Excel would with the STDEVPA() function, but I'm not getting the correct result. I'm following this formula:
Here is my [Node] code:
var _ = require('underscore');
var prices = [
1.37312,
1.35973,
1.35493,
1.34877,
1.34853,
1.35677,
1.36079,
1.36917,
1.36769,
1.3648,
1.37473,
1.37988,
1.37527,
1.38053,
1.37752,
1.38652,
1.39685,
1.39856,
1.39684,
1.39027
];
var standardDeviation = 0;
var average = _(prices).reduce(function(total, price) {
return total + price;
}) / prices.length;
var squaredDeviations = _(prices).reduce(function(total, price) {
var deviation = price - average;
var deviationSquared = deviation * deviation;
return total + deviationSquared;
});
var standardDeviation = Math.sqrt(squaredDeviations / prices.length);
console.log(standardDeviation);
When I run this, I get 0.26246286981807065, and instead I should get 0.0152.
Please note that I posted on StackOverflow and not the Mathematics site because, in my opinion, this is more geared toward programming than mathematics. If I post there, they will tell me to post here because this is related to programming.
If you console.log(total) inside your calculation of squaredDeviations, you'll see you're starting out with the value 1.37312, namely the first thing in your list. You need to explicitly tell it to start at 0, which is the third optional argument to reduce. Just replace:
var squaredDeviations = _(prices).reduce(function(total, price) {
var deviation = price - average;
var deviationSquared = deviation * deviation;
return total + deviationSquared;
});
with
var squaredDeviations = _(prices).reduce(function(total, price) {
var deviation = price - average;
var deviationSquared = deviation * deviation;
return total + deviationSquared;
}, 0);
See the underscore documentation for more details. In particular, note that things work when calculating the mean without passing this additional argument because, in said case, the iteratee function will not be applied to the first element.

Grabbing text from webpage and storing as variable

On the webpage
http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463
It lists prices for a particular item in a game, I wanted to grab the "Current guide price:" of said item, and store it as a variable so I could output it in a google spreadsheet. I only want the number, currently it is "643.8k", but I am not sure how to grab specific text like that.
Since the number is in "k" form, that means I can't graph it, It would have to be something like 643,800 to make it graphable. I have a formula for it, and my second question would be to know if it's possible to use a formula on the number pulled, then store that as the final output?
-EDIT-
This is what I have so far and it's not working not sure why.
function pullRuneScape() {
var page = UrlFetchApp.fetch("http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463").getContentText();
var number = page.match(/Current guide price:<\/th>\n(\d*)/)[1];
SpreadsheetApp.getActive().getSheetByName('RuneScape').appendRow([new Date(), number]);
}
Your regex is wrong. I tested this one successfully:
var number = page.match(/Current guide price:<\/th>\s*<td>([^<]*)<\/td>/m)[1];
What it does:
Current guide price:<\/th> find Current guide price: and closing td tag
\s*<td> allow whitespace between tags, find opening td tag
([^<]*) build a group and match everything except this char <
<\/td> match the closing td tag
/m match multiline
Use UrlFetch to get the page [1]. That'll return an HTTPResponse that you can read with GetBlob [2]. Once you have the text you can use regular expressions. In this case just search for 'Current guide price:' and then read the next row. As to remove the 'k' you can just replace with reg ex like this:
'123k'.replace(/k/g,'')
Will return just '123'.
https://developers.google.com/apps-script/reference/url-fetch/
https://developers.google.com/apps-script/reference/url-fetch/http-response
Obviously, you are not getting anything because the regexp is wrong. I'm no regexp expert but I was able to extract the number using basic string manipulation
var page = UrlFetchApp.fetch("http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463").getContentText();
var TD = "<td>";
var start = page.indexOf('Current guide price');
start = page.indexOf(TD, start);
var end = page.indexOf('</td>',start);
var number = page.substring (start + TD.length , end);
Logger.log(number);
Then, I wrote a function to convert k,m etc. to the corresponding multiplying factors.
function getMultiplyingFactor(symbol){
switch(symbol){
case 'k':
case 'K':
return 1000;
case 'm':
case 'M':
return 1000 * 1000;
case 'g':
case 'G':
return 1000 * 1000 * 1000;
default:
return 1;
}
}
Finally, tie the two together
function pullRuneScape() {
var page = UrlFetchApp.fetch("http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463").getContentText();
var TD = "<td>";
var start = page.indexOf('Current guide price');
start = page.indexOf(TD, start);
var end = page.indexOf('</td>',start);
var number = page.substring (start + TD.length , end);
Logger.log(number);
var numericPart = number.substring(0, number.length -1);
var multiplierSymbol = number.substring(number.length -1 , number.length);
var multiplier = getMultiplyingFactor(multiplierSymbol);
var fullNumber = multiplier == 1 ? number : numericPart * multiplier;
Logger.log(fullNumber);
}
Certainly, not the optimal way of doing things but it works.
Basically I parse the html page as you did (with corrected regex) and split the string into number part and multiplicator (k = 1000). Finally I return the extracted number. This function can be used in Google Docs.
function pullRuneScape() {
var pageContent = UrlFetchApp.fetch("http://services.runescape.com/m=itemdb_rs/Armadyl_chaps/viewitem.ws?obj=19463").getContentText();
var matched = pageContent.match(/Current guide price:<.th>\n<td>(\d+\.*\d*)([k]{0,1})/);
var numberAsString = matched[1];
var multiplier = "";
if (matched.length == 3) {
multiplier = matched[2];
}
number = convertNumber(numberAsString, multiplier);
return number;
}
function convertNumber(numberAsString, multiplier) {
var number = Number(numberAsString);
if (multiplier == 'k') {
number *= 1000;
}
return number;
}

Resources