how to calculate values of an (javascript) object with date keys - javascript

I have the following simplified (javascript) object, of which properties are dates (in string fomat):
Given a random startdate and enddate within the range of dates in the object, how to code (efficiently) the calculation - say accumulate- of the values within this range? As an example, for the following code the calculation result should be 12 (3+4+5) for the given startdate and enddate.
var startdate = '2014-01-03';
var enddate = '2014-01-05'
var obj = {};
obj['2014-01-02'] = '2';
obj['2014-01-03'] = '3';
obj['2014-01-04'] = '4';
obj['2014-01-05'] = '5';
obj['2014-01-06'] = '6';

You can just loop through the properties of the object, doing a comparison, and adding.
var startdate = '2014-01-04';
var enddate = '2014-01-05';
var arr = {};
arr['2014-01-02'] = '2';
arr['2014-01-03'] = '3';
arr['2014-01-04'] = '4';
arr['2014-01-05'] = '5';
arr['2014-01-06'] = '6';
var total = 0;
for(var p in arr) {
if(arr.hasOwnProperty(p)) {
if(new Date(p) >= new Date(startdate) && new Date(p) <= new Date(enddate)) {
total += parseInt(arr[p], 10);
}
}
}
console.log(total);
Sample http://jsbin.com/imUdewaJ/1/edit
I'm sure there is a better way to do this, but I don't know how due to having to parse the date object out for comparison.
--Edit added in the hasOwnProperty check from comments below

When doing stuff with dates, you might want to use thirdparty tools to handle browser compatibility. Momentjs is a good one for dates.
solution with momentjs:
var startdate = moment('2014-01-03');
var enddate = moment('2014-01-05');
var obj = {};
obj['2014-01-02'] = '2';
obj['2014-01-03'] = '3';
obj['2014-01-04'] = '4';
obj['2014-01-05'] = '5';
obj['2014-01-06'] = '6';
var strDate;
var total = 0;
for (strDate in obj) {
if (obj.hasOwnProperty(strDate)) {
var date = moment(strDate)
if (date.diff(startdate, 'days')>=0 && date.diff(enddate, 'days')<=0) {
total += parseInt(obj[strDate], 10);
}
}
}
console.log(total);

It's possible that some browsers won't support date1 > date2, so it might be better to also use getTime().
function getDate(date) {
return new Date(date).getTime();
}
function getTotal(start, end) {
var total = 0;
for (var k in obj) {
var current = getDate(k);
if (current >= start && current <= end) {
total += parseInt(obj[k], 10);
}
}
return total;
}
var start = getDate(startdate);
var end = getDate(enddate);
console.log(getTotal(start, end)); // 12

Related

Google Apps script returning every date minus one day

I assume it has something to do with timezone, but I cannot figure out how to add a day. I would like to only display the month. The issue is at the bottom of the code:
function compull() {
var linkssheet = SpreadsheetApp.openById("1hxkrSKhoUyveyK7dLr-xPpYxhZVvlKJt3S5L6rpMS7w").getSheetByName("Links");
var comsource = SpreadsheetApp.openById("1egqeIX6Lf2As2tsT0U8yhV41fg7as3dOLnwGryU9GVs");
var adjustmentssource = comsource.getSheetByName("Adjustments").getRange("A:I").getValues().filter(function(item){ return item[0] != ""; });
var compullsource = comsource.getSheetByName("Calculator").getRange("A:Q").getValues().filter(function(item){ return item[0] != ""; });
//var length = 4;
var length = 1 + getLastRowSpecial(linkssheet.getRange("E:E").getValues());
var comlength = 1 + getLastRowSpecial(compullsource);
var adjlength = 1 + getLastRowSpecial(adjustmentssource);
for (i=2; i<length; i++) {
var writelocation = SpreadsheetApp.openByUrl(linkssheet.getRange(i,5).getValue());
var compull = writelocation.getSheetByName("Commissions");
var id = linkssheet.getRange(i,1).getDisplayValue();
var id2 = linkssheet.getRange(i,2).getDisplayValue();
var rowlength = comlength;
var columnlength = compullsource[0].length;
dataarray = [];
dataarray.push(compullsource[0].slice());
for (j=1;j<compullsource.length;j++){
if(compullsource[j][1] == id){
dataarray.push(compullsource[j].slice());
}
}
for (k=0;k<dataarray.length;k++){
dataarray[k].splice(1,2);
}
compull.getRange(4,1,dataarray.length,dataarray[0].length).clearContent();
compull.getRange(4,1,dataarray.length,dataarray[0].length).setValues(dataarray);
var rowlength = adjlength;
var columnlength = adjustmentssource[0].length;
dataarray2 = [];
dataarray2.push(adjustmentssource[0].slice());
for (j=1;j<adjustmentssource.length;j++){
if(adjustmentssource[j][1] == id2){
dataarray2.push(adjustmentssource[j].slice());
}
}
for (k=0;k<dataarray2.length;k++){
dataarray2[k].splice(0,2);
}
compull.getRange(4,17,dataarray2.length,dataarray2[0].length).clearContent();
compull.getRange(4,17,dataarray2.length,dataarray2[0].length).setValues(dataarray2);
SpreadsheetApp.flush();
//change date in adjustments in Column Q
var date = compull.getRange("Q5:Q")
var values = date.getValues();
values[0][0] = Utilities.formatDate(date, "GMT-8:00", "MM");
You should know that the spreadsheet settings and the script project have their own timezone, so if you have problems with dates one of the first things that you should check is that each of them is using the correct timezone.
This part of the code is wrong
var date = compull.getRange("Q5:Q")
var values = date.getValues();
values[0][0] = Utilities.formatDate(date, "GMT-8:00", "MM");
The problem is that the first argument of formatDate should be a Date object but date had assigned a Range object.
Resources
Working with Dates and Times

Append a parameter to an array and evaluate each array element

I have a script wherein I am pushing each parameter value(Date) to an array and evaluating each element.
if(frame.name == 'bookingConfirmedMbox')
{
var checkinEligible= "false";
var currDate = Date.parse(new Date());
var depDate = frame.param(itineraryParamDate);
var departureDate = depDate.toString();
var travelDateArr = new Array();
travelDateArr.push(depDate);
console.log(travelDateArr);
var travelDateArrlen = travelDateArr.length;
for (var i=0 ; i< travelDateArrlen ; i++)
{
var travelDate = travelDateArr[i].toString();
var depaDate = travelDate.replace(/(\d{2})(\d{2})(\d{4})/, "$2/$1/$3");
var dDate= Date.parse(new Date(depaDate));
var timeDiff = parseInt(dDate - currDate);
var daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
}
if (daysDiff >= 2 && daysDiff <=7 )
{
checkinEligible="true";
}
else
{
checkinEligible="false";
}
return checkinEligible;
}
here, itineraryParamDate is the parameter name of the frame and through frame.param('itineraryParamDate') value is getting stored and appended in an array.
This script is evaluating to false if I set itineraryParamDate as 30112018 //ddmmyyyy.It should evaluate to true.
My doubt is --> var travelDate = i.toString(); is not evaluating to correct value.
Can someone advise me on this ?
function Test() {
//
var frame = new Object;
frame.name = 'bookingConfirmedMbox';
var checkinEligible = false;
var currDate = null;
var strDepDate = "";
var travelDateArr = [];
var travelDateArrlen = 0;
var travelDate = "";
var dDate = "";
var timeDiff = 0;
var daysDiff = 0;
if (frame.name == 'bookingConfirmedMbox') {
currDate = Date.parse(new Date());
strDepDate = "30112018";
travelDateArr.push(strDepDate);
travelDateArrlen = travelDateArr.length;
for (let i = 0; i < travelDateArrlen; i++) {
travelDate = strDepDate.toString();
strDepDate = travelDate.replace(/(\d{2})(\d{2})(\d{4})/, "$2/$1/$3");
dDate = Date.parse(new Date(strDepDate));
timeDiff = parseInt(dDate - currDate);
daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
}
if (daysDiff >= 2 || daysDiff <= 7) {
checkinEligible = true;
} else {
checkinEligible = false;
}
}
return checkinEligible;
} // end Test();
var retval = Test();
var res = (retval) ? "Test worked" : "Test failed";
console.log(res);
The OP has a number of issues with the code sample. If one wishes to get a true or false result, then one ought to use boolean values of true and false because "true" and "false" are non-empty strings and so each evaluates as true. If one wishes to return a value, then one must use a function which in this case is called Test(). Also, the inner if conditional needs to use a logical OR instead of a logical AND. When daysDiff holds a value of 34, as happened on Oct. 26th with this code, then the if conditional only makes sense when using a logical OR. Lastly, no need to redeclare variables in the for-loop. Better to define the values outside the loop and set with default values. In the for-loop you may reassign values to those variables.

Get the minimum and maximum dates from JSON

There JSON:
[{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}]
As in JavaScript to get the maximum and minimum date of it?
var array = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
var max = null;
var min = null;
for (var i = 0; i < array.length; i++) {
var current = array[i];
if (max === null || current.source > max.source) {
max = current;
}
if (min === null || current.source < min.source) {
min = current;
}
}
document.getElementById('maxResult').innerHTML = max.source;
document.getElementById('minResult').innerHTML = min.source;
Max: <span id="maxResult"></span><br/ >
Min: <span id="minResult"></span>
You could do something like this, provided your date format is "yyyy-MM-dd".
Convert the date string to dateKey. which always follow the ascending order as the dates proceed. 20160101(Jan 1st) is always less than 20161231(Dec 31st).
Keeping that in mind, just convert the dates to dateKey and map dateKeys to the object and just extract the max and min of the dateKeys and return the actual date.
var datesArray = [{
"source": "2016-11-02",
"sourcecount": 38
}, {
"source": "2016-11-10",
"sourcecount": 30
}, {
"source": "2016-11-31",
"sourcecount": 38
}, {
"source": "2016-01-01",
"sourcecount": 30
}];
var newObject = {};
var dates = datesArray.map(function(obj) {
var regEx = new RegExp(/-/g);
//Convert date to dateKey
var dateKey = parseInt(obj.source.replace(regEx, ""), 10)
newObject[dateKey] = obj;
return dateKey;
});
console.log("Max", newObject[Math.max(...dates)].source);
console.log("Min", newObject[Math.min(...dates)].source);
The good thing is, your date is in ISO 8601 format already. You can just simply do this,
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
var dateArr = data.map(function(v) {
return new Date(v.source);
});
// Sort the date
dateArr.sort(function(a, b) {
return a.getTime() - b.getTime();
// OR `return a - b`
});
// The highest date is in the very last of array
var highestDate = dateArr[dateArr.length - 1];
// The lowest is in the very first..
var lowestDate = dateArr[0];
Or you prefer to have your original object instead, then you can do,
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
data.sort(function(a,b) {
var date1 = (new Date(a.source));
var date2 = (new Date(b.source));
return date1 - date2;
});
// highest date is '2016-11-03'
var highestDate = data[data.length - 1].source
// lowest date is '2016-11-01'
var lowestDate = data[0].source
Try this
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}]
function compare(a,b) {
if (new Date(a.source) < new Date(b.source))
return -1;
if (new Date(a.source) > new Date(b.source))
return 1;
return 0;
}
data = data.sort(compare);
var minDate = data[0].source;
var maxDate = data[data.length - 1].source;

Javascript: reducing down to one number

So I need to take a date and convert it into one single number by adding up each digit, and when the sum exceeds 10, I need to add up the two digits. For the code below, I have 12/5/2000, which is 12+5+2000 = 2017. So 2+0+1+7 = 10 & 1+0 = 1. I get it down to one number and it works in Firebug (output of 1). However, it is not working in a coding test environment I am trying to use, so I suspect something is wrong. I know the code below is sloppy, so any ideas or help reformatting the code would be helpful! (Note: I am thinking it has to be a function embedded in a function, but haven't been able to get it to work yet.)
var array = [];
var total = 0;
function solution(date) {
var arrayDate = new Date(date);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
array.push(d,m+1,y);
for(var i = array.length - 1; i >= 0; i--) {
total += array[i];
};
if(total%9 == 0) {
return 9;
} else
return total%9;
};
solution("2000, December 5");
You can just use a recursive function call
function numReduce(numArr){
//Just outputting to div for demostration
document.getElementById("log").insertAdjacentHTML("beforeend","Reducing: "+numArr.join(","));
//Using the array's reduce method to add up each number
var total = numArr.reduce(function(a,b){return (+a)+(+b);});
//Just outputting to div for demostration
document.getElementById("log").insertAdjacentHTML("beforeend",": Total: "+total+"<br>");
if(total >= 10){
//Recursive call to numReduce if needed,
//convert the number to a string and then split so
//we will have an array of numbers
return numReduce((""+total).split(""));
}
return total;
}
function reduceDate(dateStr){
var arrayDate = new Date(dateStr);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
return numReduce([d,m+1,y]);
}
alert( reduceDate("2000, December 5") );
<div id="log"></div>
If this is your final code your function is not outputting anything. Try this:
var array = [];
var total = 0;
function solution(date) {
var arrayDate = new Date(date);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
array.push(d,m+1,y);
for(var i = array.length - 1; i >= 0; i--) {
total += array[i];
};
if(total%9 == 0) {
return 9;
} else
return total%9;
};
alert(solution("2000, December 5"));
It will alert the result in a dialog.

How to compare two different dates in dd/mm/yyyy format

Can anyone help me in finding the solution
i just want to compare two dates in dd/mm/yyyy format.
function compareDate(dt1 , dt2 , formatString){var returnVal = 2;
var dt1Parts;
var dt2Parts;
var dt1dd;
var dt1mm;
var dt1yyyy;
var dt2dd;
var dt2mm;
var dt2yyyy;
if(formatString == 'dd/mm/yyyy'){
dt1Parts = dt1.split('/');
dt2Parts = dt2.split('/');
dt1dd = parseInt(dt1Parts[0]);
dt1mm = parseInt(dt1Parts[1]);
dt1yyyy = parseInt(dt1Parts[2]);
dt2dd = parseInt(dt2Parts[0]);
dt2mm = parseInt(dt2Parts[1]);
dt2yyyy = parseInt(dt2Parts[2]);
}
else if(formatString == 'dd-mm-yyyy'){
dt1Parts = dt1.split('-');
dt2Parts = dt2.split('-');
dt1dd = parseInt(dt1Parts[0]);
dt1mm = parseInt(dt1Parts[1]);
dt1yyyy = parseInt(dt1Parts[2]);
dt2dd = parseInt(dt2Parts[0]);
dt2mm = parseInt(dt2Parts[1]);
dt2yyyy = parseInt(dt2Parts[2]);
}else{
alert(formatString+' format is not supported.');
}
if(dt1yyyy == dt2yyyy && dt1mm == dt2mm && dt1dd == dt2dd){
returnVal = 0;
}
else if(dt1yyyy > dt2yyyy){
returnVal = 1 ;
}else if(dt1yyyy == dt2yyyy ){
if(dt1mm > dt2mm){
returnVal = 1;
}else if(dt1mm == dt2mm){
if(dt1dd > dt2dd){
returnVal = 1;
}else{
returnVal = -1;
}
}else{
returnVal = -1;
}
}else{
returnVal = -1;
}
return returnVal;
}
Thanks in advance,
Shilpa
Invert the strings to yyyy/mm/dd, or convert them to a number or Date object.
The simplest way just for comparison would be ASCII order. Invert using something like this:
function invert(date) {
return date.split(/[/-]/).reverse().join("")
}
function compareDates(date1, date2) {
return invert(date1).localeCompare(invert(date2));
}
Here's how you convert that string format to a date:
var myString = "17/07/1979",
correctFormat = myString.replace(/(\d+)\/(\d+)\/(\d+)/, "$3/$2/$1"),
myDate = new Date(correctFormat);
Without knowing what language or class libs you're working with:
Method 1: Resort your strings to be yyyymmdd and the do string compare.
Method 2: Stuff yyyy mm and dd into the high, middle, and low bits of an integer and compare.
The easiest way is probably to create 2 javascript Date objects from your input string. You could achieve that by chopping your input into day, month and year. You can use the 'substring' function for that.
Then you can do:
var firstDate = new Date(year1, month1, day1);
var secondDate = new Date(year2, month2, day2);
Once you have 2 date objects, you can use the normal compare operators:
if (firstDate > secondDate)
// do something
else
...
Try this
var date1=new Date('your date1 string');
var date2=new Date('your date2 string');
var difference=new Date(date1.getTime()-date2.getTime());
if ($.datepicker.parseDate('dd/mm/yy', fDate) > $.datepicker.parseDate('dd/mm/yy', tDate)) {
//do something
}
You can compare two dates.Here I compare from date greater than to date
try this

Categories

Resources