jQuery Javascript Group Years by Decades - javascript

I have the below which loops through each div and returns the year that each div represents, but what I'd like to do is group the returned years into arrays of the decades. I'm not quite sure how to do that and was hoping someone could help with this.
<div class="timeline-events timeline-year-1994">This is 1994<div>
<div class="timeline-events timeline-year-1997">This is 1997<div>
<div class="timeline-events timeline-year-2001">This is 2001<div>
<div class="timeline-events timeline-year-2003">This is 2003<div>
<div class="timeline-events timeline-year-2012">This is 2012<div>
$('.timeline-events').each(function(){
console.log(this.className.match(/timeline-year-(\d+)?/)[1]);
});
jsFiddle

You can work out the decade of a year by dividing by ten, flooring it and multiplying the result.
From there on out it's grouping by your decade and merging it into your object:
var groupedByDecade = {};
$('.timeline-events').each(function(){
var year = this.className.match(/timeline-year-(\d+)?/)[1],
decade = Math.floor(year/10)*10;
groupedByDecade[decade] = $.merge(groupedByDecade[decade] || [], [year]);
});
JSFiddle

If i understood your question correctly;
var decades = {};
$('.timeline-events').each(function(){
var year = this.className.match(/timeline-year-(\d+)?/)[1];
var decade = year.substring(0,3) + "0";
if (decades.hasOwnProperty( decade )) {
decades[ decade ].push(year);
} else {
decades[ decade ] = [ year ];
}
});
console.log(JSON.stringify(decades));
this creates an object with "decades" as property name which are of the type array, where the array contains the years.

UPDATED for grouping using underscore.
http://jsfiddle.net/9o39jxLo/1/
var data = [];
var decadedata = new Array();
$(function() {
$('.timeline-events').each(function(){
var year = (this.className.match(/timeline-year-(\d+)?/)[1]);
var decade = year - (year % 10);
data.push({ "decade": decade, "year": year});
});
});
function testdecade(){
var groupedData = _.groupBy(data, function(d){return d.decade});
console.log(groupedData);
}

One approach:
// iterate over each of the '.timeline-events' elements:
$('.timeline-events').each(function() {
// finding first the specific (four-digit) year,
// then getting a substring, for the decade and adding a 0:
var decade = (/timeline\-year\-(\d{4})/).exec(this.className)[1].substring(2, 3) + '0',
// if the previous element to the current element is a decade-grouping element and
// it's the appropriate decade, we use that element; otherwise we create a new one:
decadeDiv = $(this).prev('.decade-' + decade).length ? $(this).prev('.decade-' + decade) : $('<div />', {
'class': 'decade-' + decade
// and insert that element before the current element:
}).insertBefore(this);
// we then append this element to the decade grouping element:
$(this).appendTo(decadeDiv);
});
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="timeline-events timeline-year-1994">This is 1994
</div>
<div class="timeline-events timeline-year-1997">This is 1997
</div>
<div class="timeline-events timeline-year-2001">This is 2001
</div>
<div class="timeline-events timeline-year-2003">This is 2003
</div>
<div class="timeline-events timeline-year-2012">This is 2012
</div>
In response to the clarification, in the comments to the question, that you'd like a JSON string, I'd suggest (assuming you want the HTML of the elements) the following:
var decadeGroups = {};
$('.timeline-events').map(function () {
var decade = [].filter.call(this.classList, function (cName) {
return cName.indexOf('timeline-year-') === 0;
}).join('').match(/\d{2}$/)[0].replace(/\d$/, '0');
if (decadeGroups[decade]) {
decadeGroups[decade].push(this.outerHTML);
}
else {
decadeGroups[decade] = [this.outerHTML];
}
});
console.log(JSON.stringify(decadeGroups));
// initialising an object:
var decadeGroups = {};
// iterating over the '.timeline-events' elements:
$('.timeline-events').each(function() {
// reducing the array-like classList,
var decade = [].filter.call(this.classList, function(cName) {
// keeping only the class-name that starts with 'timeline-year-':
return cName.indexOf('timeline-year-') === 0;
// turning that into a string with join('')
// matching the last two digits of the year,
// replacing the last digit with a zero:
}).join('').match(/\d{2}$/)[0].replace(/\d$/, '0');
// if the object has a key of the current decade:
if (decadeGroups[decade]) {
// we add the outerHTML of the current element to that array:
decadeGroups[decade].push(this.outerHTML);
} else {
// otherwise we create a new object key, and assign an array
// containing the outerHTML of the current element:
decadeGroups[decade] = [this.outerHTML];
}
});
// logging the JSON-stringified object:
console.log(JSON.stringify(decadeGroups));
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="timeline-events timeline-year-1994">This is 1994
</div>
<div class="timeline-events timeline-year-1997">This is 1997
</div>
<div class="timeline-events timeline-year-2001">This is 2001
</div>
<div class="timeline-events timeline-year-2003">This is 2003
</div>
<div class="timeline-events timeline-year-2012">This is 2012
</div>
References:
JavaScript:
Array.prototype.filter().
Array.prototype.join().
Element.classList.
Function.prototype.call().
JSON.stringify().
String.indexOf().
String.prototype.match().
jQuery:
appendTo().
each().
insertBefore().
prev().

Related

sort divs based on dates - javascript

I have divs with data attribute data-submit-date and i want to sort them based on the value of this attribute which is date format.
here's the code for one of the divs:
<div class="article" data-submit-date="2017-09-12T05:45:36.951Z">
<h1>aaaaA</h1>
</div>
my attempts:
$divss = $(".article");
var alphaOrderDivs = $divss.sort(function (a, b) {
return $(a).data("submit-date") > $(b).data("submit-date");
});
$(".articles").html(alphaOrderDivs);
I replaced this line $(a).data("submit-date") with Date.parse($(a).data("submit-date")) but it fails. Can anyone help me?
Thank In Advance
Try the following
var articles = $.makeArray($(".article"));
articles.sort(function(a, b) {
return new Date($(a).data("submit-date")) < new Date($(b).data("submit-date"));
});
Snippet
var articles = $.makeArray($(".article"));
articles.sort(function(a, b) {
return new Date($(a).data("submit-date")) < new Date($(b).data("submit-date"));
});
console.log(articles);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="article" data-submit-date="2017-09-10T05:45:36.951Z">
<h1>aaaaA</h1>
</div>
<div class="article" data-submit-date="2017-09-12T05:45:36.951Z">
<h1>aaaaA</h1>
</div>
<div class="article" data-submit-date="2017-09-11T05:45:36.951Z">
<h1>aaaaA</h1>
</div>
Use the getTime() method as follows:
$divss = $(".article");
var alphaOrderDivs = $divss.sort(function (a, b) {
return new Date($(a).data("submit-date")).getTime() > new Date($(b).data("submit-date")).getTime();
});
$(".articles").html(alphaOrderDivs);
The getTime() method of the Date object will parse your time into milliseconds and will hence help you compare them.

How to replace numbers in a div?

With the following code, I'm getting the values of "id"(almost 35), and then add 1 to each "id", so 1 will be 2 and so on. Where I'm stock, it is on how to replace that id number in the html.
This is the code that use to get the values of each id, then I push them into an array, then I run another "for loop" to add 1 to each value, but I don't how to return them to the html.
var x = document.getElementsByClassName('p-divs');
var portfolio = new Array;
for (var i = 0; i < x.length; i++)
{
var y = document.getElementsByClassName('p-divs')[i].getAttribute('id');
portfolio.push(y);
}
console.log(portfolio);
var portfolio2 = new Array;
for (var i = 0; i<portfolio.length; i++)
{
var newId;
newId = parseInt(portfolio[i]) + 1;
portfolio2.push(newId);
}
console.log(portfolio2);
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12 p-divs" id="1">
<div class="portfolio">
<center>
<img src="images/pace.png" width="230" height="190" alt="" class="img-responsive">
</center>
</div>
</div>
Since you're using jQuery library the code could be simple than what you've so far using .each() method :
$('.p-divs').each(function(){
$(this).attr('id', Number(this.id) + 1);
});
Or shorter using using .attr() method callback like :
$('.p-divs').attr('id', function(){
return Number(this.id) + 1;
});
The more clear version could be :
$('.p-divs').each(function(){
var current_id = Number(this.id); //Get current id
var new_id = current_id + 1; //Increment to define the new one
$(this).attr('id', new_id); //Set the new_id to the current element 'id'
});
Hope this helps.
$(function(){
$('.p-divs').attr('id', function(){
return Number(this.id) + 1;
});
//Just for Debug
console.log( $('body').html() );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="p-divs" id="1">
<div class="portfolio">
<center>Image 1</center>
</div>
</div>
<div class="p-divs" id="2">
<div class="portfolio">
<center>Image 2</center>
</div>
</div>
<div class="p-divs" id="3">
<div class="portfolio">
<center>Image 3</center>
</div>
</div>
<div class="p-divs" id="4">
<div class="portfolio">
<center>Image 4</center>
</div>
</div>
Using native javascript, just use getattribute's opposite: setAttribute
for (var i = 0; i < x.length; i++)
{
var y = document.getElementsByClassName('p-divs')[i].getAttribute('id');
y++;
document.getElementsByClassName('p-divs')[i].setAttribute("id",y);
}
var j = document.getElementsByClassName('p-divs');
for (var i = 0; i < x.length; i++) {
j[i].id = portfolio2[i];
}
Add this to the end of your code. Vanilla JS.
j will be an array of your divs, i will keep count of which div we're on, and we are simply accessing the "id" of each element in the "j" array and updating it to the corresponding value in your pre-populated "portfolio2" array.
Hope this helps!
P.S.- I would also recommend that instead of using 'new Array' to instantiate your arrays, you use the array literal notation '[]'. This is more concise and also avoids needing to put (); after Array.
I'd suggest, assuming I'm not missing something, and that you're able to us ES6 methods:
// converting the NodeList returned from document.querySelectorAll()
// into an Array, and iterating over that Array using
// Array.prototype.forEach():
Array.from( document.querySelectorAll('.p-divs') ).forEach(
// using an Arrow function to work with the current element
// (divElement) of the Array of elements,
// here we use parseInt() to convert the id of the current
// element into a number (with no sanity checking), adding 1
// and assigning that result to be the new id:
divElement => divElement.id = parseInt( divElement.id, 10 ) + 1
);
Note that updating, changing or otherwise modifying an id shouldn't be necessary in most circumstances, and having a purely numeric id may present problems for CSS selecting those elements (it's valid, but only in HTML 5, but will still be problematic).
for(i=0;i<$('.p-divs').length;i++){
newId= parseInt($($('.p-divs')[i]).attr('id'))+1;
$($('.p-divs')[i]).attr('id',newId)
}
Using Jquery attr

Sort divs by date / time with JS

I have a script which creates a lot of divs with the a data-date attribute and has a time format of Tue Aug 16 2016 12:27:21 GMT+0100 (BST)
An example set could be:
<div class="socialBox" data-date="Tue Aug 10 2016 12:30:21 GMT+0100 (BST)" data-type="twitter">
<div class="socialBox" data-date="Tue Aug 14 2016 12:10:21 GMT+0100 (BST)" data-type="facebook">
<div class="socialBox" data-date="Tue Aug 13 2016 15:27:21 GMT+0100 (BST)" data-type="youtube">
<div class="socialBox" data-date="Tue Aug 03 2016 18:27:21 GMT+0100 (BST)" data-type="instagram">
The divs are appended to a blank div from a variety of different functions and then I run the JS to sort the divs and append it to the original blank div again but I can't seem to get it to work.
Here is the script
loadTwitter(twitter);
loadFacebook(facebook);
loadYoutube(youtube);
loadInstagram(instagram);
// DOESN'T WORK YET (THE BELOW)
var board = $("#social-board");
var boards = board.children('.socialBox');
boards.sort(function(a, b) {
var an = $(a).data("date").getTime();
var bn = $(b).data("date").getTime();
if(an > bn) {
return 1;
}
if(an < bn) {
return -1;
}
return 0;
});
boards.detach().appendTo(board);
Could anyone help me out? I'm not sure if its the appending to the div element or the JS sort function itself.
You can do this by:
Detaching them up front and then using .get to get a real array instead of a jQuery object.
Sorting them (which can be a lot simpler)
Appending that array back to #social-board
so:
var boards = board.children('.socialBox').detach().get();
// --------------------------------------^^^^^^^^^^^^^^^
// A bit shorter :-)
boards.sort(function(a, b) {
return new Date($(a).data("date")) - new Date($(b).data("date"));
});
board.append(boards); // <== switched this to append
Live example:
// Wait a sec so we can see the old order...
setTimeout(function() {
// Now sort them
var board = $("#social-board");
var boards = board.children('.socialBox').detach().get();
boards.sort(function(a, b) {
return new Date($(a).data("date")) - new Date($(b).data("date"));
});
board.append(boards);
}, 600);
<div id="social-board">
<div class="socialBox" data-date="2016-08-10T11:30:21.000Z" data-type="twitter">2016-08-10T11:30:21.000Z</div>
<div class="socialBox" data-date="2016-08-03T17:27:21.000Z" data-type="instagram">2016-08-03T17:27:21.000Z</div>
<div class="socialBox" data-date="2016-08-14T11:10:21.000Z" data-type="facebook">2016-08-14T11:10:21.000Z</div>
<div class="socialBox" data-date="2016-08-13T14:27:21.000Z" data-type="youtube">2016-08-13T14:27:21.000Z</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Note: You cannot rely on the JavaScript Date object parsing dates in the string format you've used. Note the ISO format I've used in the snippet instead.
Side note: Unless you're using the features of data, you may want to use attr instead. data is not just an accessor for data-* attributes. It's both more and less than that.
Your idea is right, but your logic is slightly off in your sort function. This is the code I use to sort dates:
var reverse = false; // ascending/descending flag
var board = $("#social-board");
var boards = board.children('.socialBox');
var orderedBoards = boards.slice().sort(function (elem1, elem2) {
var value1 = new Date($(elem1).data("date")).getTime(),
value2 = new Date($(elem2).data("date")).getTime();
if (reverse) {
// descending
return -(value1 > value2) || +(value1 < value2) || (isNaN(value1)) - (isNaN(value2));
}
// ascending
return +(value1 > value2) || -(value1 < value2) || (isNaN(value1)) - (isNaN(value2));
});
board.empty().append(orderedBoards);
I have a solution:
HTML:
<ul class="sort-list">
<li class="sort-item" data-event-date="2018-06-30 22:00">3</li>
<li class="sort-item" data-event-date="2018-06-29 21:00">2</li>
<li class="sort-item" data-event-date="2018-06-27 22:00">1</li>
<li class="sort-item" data-event-date="2018-07-01 22:00">4</li>
<li class="sort-item" data-event-date="2018-07-02 22:00">5</li>
</ul>
<button onclick="chat_order()">
test
</button>
JS:
function chat_order() {
var container = $(".sort-list");
var items = $(".sort-item");
items.each(function() {
// Convert the string in 'data-event-date' attribute to a more
// standardized date format
var BCDate = $(this).attr("data-event-date");
/*console.log(BCDate);
var standardDate = BCDate[1]+" "+BCDate[0]+" "+BCDate[2];*/
var standartDate = new Date(BCDate).getTime();
$(this).attr("data-event-date", standartDate);
console.log(standartDate);
});
items.sort(function(a,b){
a = parseFloat($(a).attr("data-event-date"));
b = parseFloat($(b).attr("data-event-date"));
return a>b ? -1 : a<b ? 1 : 0;
}).each(function(){
container.prepend(this);
});
}
JSFIDDLE: http://jsfiddle.net/2fr0vmhu/294/

CLNDR - How to get Today, Tomorrow and Current Month event list and count and print that information to separate div

Hi I'm using CLNDR and trying to get today, tomorrow and this month event list and event count information into separate div, I did try various things but couldn't find a better solution, can anyone, please help me with this. below code is for reference.
doneRendering: function() {
// make a moment object representing today
var target = moment();
var tommorow = target.add(1,'days');
var eventsTommorow =[];
if(this.options.multiDayEvents) {
eventsTommorow = $.makeArray( $(this.options.events).filter( function() {
// filter the dates down to the ones that match.
return ( ( tommorow.isSame(this._clndrStartDateObject, 'day') || tommorow.isAfter(this._clndrStartDateObject, 'day') ) &&
( tommorow.isSame(this._clndrEndDateObject, 'day') || tommorow.isBefore(this._clndrEndDateObject, 'day') ) );
}) );
} else {
eventsTommorow = $.makeArray( $(this.options.events).filter( function() {
// filter the dates down to the ones that match.
return this._clndrDateObject.format('YYYY-MM-DD') == dateString;
}) );
}
if(eventsTommorow.length) {
console.log(eventsTommorow.length);
var newNum = eventsTommorow.length < 10 ? "0" + eventsTommorow.length : eventsTommorow.length;
return $('.td-emp-count.tdTommorow').text(newNum);
}
}
},
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Actually, my problem is I can not filter events and print them into separate div, I tried moment.js validation to get today event. but it didn;t work as expected. but finally I tried a simple method to get today, tomorrow and this month event count and it worked. but the problem is if a recurring event happens, let's say maternity leave start on 24th April to 30th may then I can not get between event counts. because I'm capturing CLNDR date, startDate, endDate there is no way to get between events count. please find the code
doneRendering: function() {
// make a moment object representing today
var _self = this;
function todayCount() {
var totalDate = _.filter(_self.options.events, {
date: moment().format('YYYY-MM-DD')
});
var totalStartDate = _.filter(_self.options.events, {
startDate: moment().format('YYYY-MM-DD')
});
var totalEndDate = _.filter(_self.options.events, {
endDate: moment().format('YYYY-MM-DD')
});
var newNum = (totalDate.length + totalStartDate.length + totalEndDate.length) < 10 ? "0" + (totalDate.length + totalStartDate.length + totalEndDate.length) : (totalDate.length + totalStartDate.length + totalEndDate.length);
return newNum;
}
$('.td-emp-count.tdToday').text(todayCount());
},
This is a simple hack and I'm using underscore.js. but this way I cannot get actual today count, the reason is if a recurring leave happens it cannot get middle leave day as a count
eg:
Sick leave
startDate = 24th April 2016
endDate = 28th April 2016
when I apply my simple hack to this, I can only get 24th April (Monday) as one count and 28th April (Friday) as another count but when I try to print Wednesday leave counts, it cannot get this day as a leave count,
I'm new to underscore.js but I really need to know how to print these variables into underscore.js template,
Within template event count.
I can get the today (actual leave) count by using _.each() method and print them on into day itself like this one
<% _.each(days, function(day) { %>
<div class="<%= day.classes %>" id="<%= day.id %>">
<div class="num"><%= day.day %></div>
<% if (day.events.length) { %>
<div class="eventsTitles">Leave : <strong><%= day.events.length %></strong></div>
<% } %>
<ul class="dayLeaveTypes">
<% _.each(day.events, function(event) { %>
<li title="<%= event.type %>" id="<%= event.type %>" style="color:<%= event.color %>;">●</li>
<% }); %>
</ul>
</div>
<% }); %>
but I need to get this actual count (only specific day today or tomorrow) and print them into separate div, not within the calendar.
this is the whole idea i'm trying to solve. :)

Group JSON data into weeks / months without additional external library?

I am looking for a solution to group data into weeks / months without external library. I have seen the D3.js nest() option here: how can i group JSON data into the weeks according to calender?
Here another way using npm: https://www.npmjs.com/package/group-by-time
Maybe I am crazy having grown up in the age of dialup, but I still like to keep how many things I load on a page down to what is actually needed instead of loading everything possible, just in case I want to use it, even though the user "might" already have a cached copy from a CDN.
I am currently using Chart.js to display data, also available are Bootstrap and jQuery. I would love to be able to switch the chart between day, week month, using only javascript or jQuery, which seems like it should be a fairly common thing, but I don't see any examples without going for a bigger library like I mentioned above.
var chart={
dates: ['2015-09-01', '2015-09-02', '2015-09-03', '2015-09-04', '2015-09-05', '2015-09-06', '2015-09-07', '2015-09-08', '2015-09-09', '2015-09-10', '2015-09-11', '2015-09-12', '2015-09-13', '2015-09-14', '2015-09-15', '2015-09-16', '2015-09-17', '2015-09-18', '2015-09-19', '2015-09-20', '2015-09-21', '2015-09-22', '2015-09-23', '2015-09-24', '2015-09-25', '2015-09-26', '2015-09-27', '2015-09-28', '2015-09-29', '2015-09-30', '2015-10-01', '2015-10-02', '2015-10-03', '2015-10-04', '2015-10-05', '2015-10-06', '2015-10-07', '2015-10-08', '2015-10-09', '2015-10-10', '2015-10-11', '2015-10-12', '2015-10-13', '2015-10-14', '2015-10-15', '2015-10-16', '2015-10-17', '2015-10-18', '2015-10-19', '2015-10-20', '2015-10-21', '2015-10-22', '2015-10-23', '2015-10-24', '2015-10-25', '2015-10-26', '2015-10-27', '2015-10-28', '2015-10-29', '2015-10-30', '2015-10-31', '2015-11-01', '2015-11-02', '2015-11-03', '2015-11-04', '2015-11-05', '2015-11-06', '2015-11-07', '2015-11-08', '2015-11-09', '2015-11-10', '2015-11-11', '2015-11-12', '2015-11-13', '2015-11-14', '2015-11-15', '2015-11-16', '2015-11-17', '2015-11-18', '2015-11-19', '2015-11-20', '2015-11-21', '2015-11-22', '2015-11-23', '2015-11-24', '2015-11-25', '2015-11-26', '2015-11-27', '2015-11-28', '2015-11-29', '2015-11-30', '2015-12-01', '2015-12-02', '2015-12-03', '2015-12-04', '2015-12-05', '2015-12-06', '2015-12-07', '2015-12-08', '2015-12-09', '2015-12-10', '2015-12-11', '2015-12-12', '2015-12-13', '2015-12-14', '2015-12-15', '2015-12-16', '2015-12-17', '2015-12-18', '2015-12-19', '2015-12-20', '2015-12-21', '2015-12-22', '2015-12-23', '2015-12-24', '2015-12-25', '2015-12-26', '2015-12-27', '2015-12-28', '2015-12-29', '2015-12-30', '2015-12-31', '2016-01-01', '2016-01-02', '2016-01-03', '2016-01-04', '2016-01-05', '2016-01-06', '2016-01-07', '2016-01-08', '2016-01-09', '2016-01-10', '2016-01-11', '2016-01-12', '2016-01-13', '2016-01-14', '2016-01-15', '2016-01-16', '2016-01-17', '2016-01-18', '2016-01-19', '2016-01-20', '2016-01-21', '2016-01-22', '2016-01-23', '2016-01-24', '2016-01-25', '2016-01-26', '2016-01-27', '2016-01-28', '2016-01-29', '2016-01-30', '2016-01-31', '2016-02-01', '2016-02-02', '2016-02-03', '2016-02-04', '2016-02-05', '2016-02-06', '2016-02-07', '2016-02-08', '2016-02-09', '2016-02-10', '2016-02-11', '2016-02-12', '2016-02-13', '2016-02-14', '2016-02-15', '2016-02-16', '2016-02-17', '2016-02-18', '2016-02-19', '2016-02-20', '2016-02-21', '2016-02-22', '2016-02-23', '2016-02-24', '2016-02-25', '2016-02-26', '2016-02-27', '2016-02-28', '2016-02-29'],
data: [77.02, 63.80, 21.64, 86.60, 65.40, 46.25, 27.38, 66.65, 67.25, 65.59, 64.80, 01.00, 32.75, 04.30, 51.92, 02.75, 40.20, 72.30, 62.90, 83.60, 66.66, 37.30, 93.90, 01.50, 55.77, 50.00, 73.20, 30.03, 07.95, 21.65, 07.93, 66.94, 11.72, 33.75, 22.80, 14.55, 68.78, 66.78, 52.35, 06.24, 64.78, 22.21, 19.08, 23.69, 54.40, 39.55, 28.76, 22.25, 09.85, 07.50, 22.47, 75.94, 93.34, 16.29, 28.98, 64.40, 78.68, 30.65, 96.65, 99.35, 77.50, 75.30, 89.85, 97.50, 53.90, 97.55, 28.98, 75.08, 25.66, 41.00, 73.72, 68.50, 95.40, 49.50, 32.50, 86.00, 05.43, 88.19, 50.39, 03.90, 82.90, 53.78, 94.20, 82.40, 12.63, 78.80, 07.50, 66.50, 41.75, 91.25, 34.50, 22.50, 85.50, 80.00, 33.75, 59.50, 52.50, 73.25, 76.50, 38.75, 11.00, 55.00, 37.25, 92.50, 74.75, 55.75, 37.25, 61.01, 90.95, 87.65, 99.08, 84.49, 47.00, 72.20, 45.95, 44.35, 10.90, 27.05, 63.10, 63.50, 66.48, 97.25, 39.85, 81.50, 57.90, 02.78, 72.95, 41.55, 39.44, 15.85, 06.60, 13.60, 87.10, 86.40, 90.75, 48.30, 29.75, 16.25, 20.51, 45.40, 51.10, 82.00, 24.24, 92.88, 81.75, 18.50, 89.15, 55.75, 53.50, 74.90, 41.35, 61.40, 07.80, 56.80, 33.75, 75.02, 78.50, 46.10, 39.25, 95.00, 22.85, 36.00, 43.53, 63.80, 32.85, 88.30, 89.69, 05.75, 16.15, 15.25, 20.55, 44.50, 46.28, 71.75, 19.45, 41.75, 25.75, 09.05, 58.77, 76.20, 30.45, 71.75]
};
I'm assuming that date format is YYYY-MM-DD as in sample and for convenience I'm saving both dates and data in different arrays.
var dates = chart.dates;
var data = chart.data;
Keeping above assumptions in mind, you can easily group data by months.
var groupByMonth = {};
dates.forEach(function (d, i) {
var v = data[i];
var monthYear = d.slice(0, 7);
if (groupByMonth.hasOwnProperty(monthYear)) {
groupByMonth[monthYear].push(v);
} else {
groupByMonth[monthYear] = [v];
}
});
console.log(groupByMonth)
However to group by week, you need to find week number. Here is a extension method to do that so:
Date.prototype.getWeekNumber = function(){
var d = new Date(+this);
d.setHours(0,0,0);
d.setDate(d.getDate()+4-(d.getDay()||7));
return Math.ceil((((d-new Date(d.getFullYear(),0,1))/8.64e7)+1)/7);
};
Using above extension method you can easily group data by week number too. Week number repeats in each year so, I'm using combination of week and year to uniqly identify any week.
var groupByWeek = {};
dates.forEach(function (d, i) {
var v = data[i];
var weekYear = d.slice(0, 4) + '-' + new Date(d).getWeekNumber();
if (groupByWeek.hasOwnProperty(weekYear)) {
groupByWeek[weekYear].push(v);
} else {
groupByWeek[weekYear] = [v];
}
});
console.log(groupByWeek)
#Adnan Umer´s solution is probably better for your case since you already have the dates as strings, but here is a more general method in case you had the date instead of string:
function roundDate(date,type){
var d = new Date(date) // so as to not override
var types = ["day","week","month"]
var idx = types.indexOf(type)
if(idx > -1){ // remove all less than day
d.setMilliseconds(0)
d.setSeconds(0)
d.setMinutes(0)
d.setHours(0)
if(idx > 0){ //remove day of the week
d.setDate(d.getDate() - d.getDay()) // make it a sunday
if(idx > 1){ //remove day of month
d.setDate(1)
}
}
}
return d;
}
function parseDate(str){ // in your case, we need to keep the date disregarding the locale offset
return new Date(new Date(str).getTime() + new Date().getTimezoneOffset()*60*1000)
}
var lastDate = null
var grouping = "month"
var datesGrouped = []
var dataGrouped = []
function addToLast(arr,val){return arr[arr.length-1]+=val}
//I am assumming your dates are already sorted
chart.dates.map(function(date,index){
data = chart.data[index] // get corresponding data point
var group = roundDate(parseDate(date),grouping).getTime()
if(group == lastDate){
addToLast(dataGrouped, data)
}else{
datesGrouped.push(group)
dataGrouped.push(data)
lastDate = group
}
})
console.log(datesGrouped, dataGrouped)

Categories