I am going though a project an attempting to remove unnecessary 3rd party dependencies in places where native JS accomplishes the job. We use Underscore's _.sortBy
to sort an array of dates, but for some reason I can't quite duplicate the exact sort order yet.
The data comes back unsorted and looks like this:
{
"title": "February 2016",
"startTime": "2016-02-01T10:00:00.000Z",
"endTime": "2016-03-01T09:59:59.000Z"
},
{
"title": "Week of February 28 2016",
"startTime": "2016-02-28T05:00:00.000Z",
"endTime": "2016-03-06T04:59:59.000Z"
},
{
"title": "March 2016",
"startTime": "2016-03-01T10:00:00.000Z",
"endTime": "2016-04-01T07:59:59.000Z"
},
{
"title": "Week of March 06 2016",
"startTime": "2016-03-06T05:00:00.000Z",
"endTime": "2016-03-13T04:59:59.000Z"
},
{
"title": "Week of March 13 2016",
"startTime": "2016-03-13T05:00:00.000Z",
"endTime": "2016-03-20T03:59:59.000Z"
},
Basically it needs just standard date sorting, except the "week of..." ranges should appear before the entire month range.
This is how it is done currently using Underscore & MomentJS (also using Typescript), this correctly sorts it exactly how we want:
_.sortBy(dateRanges, (range: IDateRange) => {
if (moment(range.endTime).diff(range.startTime, "days") > 7) {
return range.endTime;
} else {
return range.startTime;
}
});
I am attempting to duplicate that exact output, but without using Underscore or MomentJS. Here's what I have so far:
dateRanges.sort((r1: IDateRange, r2: IDateRange) => {
//604800000 milliseconds in 1 week
//easier to hard code number this than do all the math on each iteration here
const isWholeMonth = r1.endTime.getTime() - r1.startTime.getTime() > 604800000;
if (isWholeMonth) {
if (r1.endTime > r2.endTime) {
return 1;
} else if (r1.endTime < r2.endTime) {
return -1;
}
return 0;
} else {
//Make the week listings for a month appear before the entire month listings
if (r1.startTime > r2.startTime) {
return 1;
} else if (r1.startTime < r2.startTime) {
return -1;
}
return 0;
}
});
It's not entirely sorting correctly yet, but I can't quite figure out why. Here's a working demo that outputs both of those to the console so the
http://codepen.io/chrismbarr/pen/KWOaaE
答案 0 :(得分:1)
Underscore's _sortBy
works differently than native sort
. You need to check and compare different things, depending on if you have the 'week'
present in the title or not (or check startTime and endTime, up to you):
interface IDateRange {
title: string;
startTime: Date;
endTime: Date;
}
const dateRanges: IDateRange[] = [
{
"title": "February 2016",
"startTime": "2016-02-01T10:00:00.000Z",
"endTime": "2016-03-01T09:59:59.000Z"
},
{
"title": "Week of February 28 2016",
"startTime": "2016-02-28T05:00:00.000Z",
"endTime": "2016-03-06T04:59:59.000Z"
},
{
"title": "March 2016",
"startTime": "2016-03-01T10:00:00.000Z",
"endTime": "2016-04-01T07:59:59.000Z"
},
{
"title": "Week of March 06 2016",
"startTime": "2016-03-06T05:00:00.000Z",
"endTime": "2016-03-13T04:59:59.000Z"
},
{
"title": "Week of March 13 2016",
"startTime": "2016-03-13T05:00:00.000Z",
"endTime": "2016-03-20T03:59:59.000Z"
},
{
"title": "October 2016",
"startTime": "2016-10-01T08:00:00.000Z",
"endTime": "2016-11-01T07:59:59.000Z"
},
{
"title": "Week of October 02 2016",
"startTime": "2016-10-02T04:00:00.000Z",
"endTime": "2016-10-09T03:59:59.000Z"
},
{
"title": "Week of October 30 2016",
"startTime": "2016-10-30T04:00:00.000Z",
"endTime": "2016-11-06T03:59:59.000Z"
},
{
"title": "November 2016",
"startTime": "2016-11-01T08:00:00.000Z",
"endTime": "2016-12-01T09:59:59.000Z"
},
{
"title": "Week of November 13 2016",
"startTime": "2016-11-13T05:00:00.000Z",
"endTime": "2016-11-20T04:59:59.000Z"
},
{
"title": "Week of November 20 2016",
"startTime": "2016-11-20T05:00:00.000Z",
"endTime": "2016-11-27T04:59:59.000Z"
},
{
"title": "Week of November 27 2016",
"startTime": "2016-11-27T05:00:00.000Z",
"endTime": "2016-12-04T04:59:59.000Z"
},
{
"title": "December 2016",
"startTime": "2016-12-01T10:00:00.000Z",
"endTime": "2017-01-01T09:59:59.000Z"
},
{
"title": "Week of December 04 2016",
"startTime": "2016-12-04T05:00:00.000Z",
"endTime": "2016-12-11T04:59:59.000Z"
},
{
"title": "Week of December 11 2016",
"startTime": "2016-12-11T05:00:00.000Z",
"endTime": "2016-12-18T04:59:59.000Z"
},
{
"title": "Week of December 25 2016",
"startTime": "2016-12-25T05:00:00.000Z",
"endTime": "2017-01-01T04:59:59.000Z"
},
{
"title": "January 2017",
"startTime": "2017-01-01T10:00:00.000Z",
"endTime": "2017-02-01T09:59:59.000Z"
},
{
"title": "Week of January 15 2017",
"startTime": "2017-01-15T05:00:00.000Z",
"endTime": "2017-01-22T04:59:59.000Z"
},
{
"title": "Week of January 29 2017",
"startTime": "2017-01-29T05:00:00.000Z",
"endTime": "2017-02-05T04:59:59.000Z"
},
{
"title": "February 2017",
"startTime": "2017-02-01T10:00:00.000Z",
"endTime": "2017-03-01T09:59:59.000Z"
},
{
"title": "Week of February 05 2017",
"startTime": "2017-02-05T05:00:00.000Z",
"endTime": "2017-02-12T04:59:59.000Z"
},
{
"title": "Week of February 12 2017",
"startTime": "2017-02-12T05:00:00.000Z",
"endTime": "2017-02-19T04:59:59.000Z"
},
{
"title": "March 2017",
"startTime": "2017-03-01T10:00:00.000Z",
"endTime": "2017-04-01T07:59:59.000Z"
},
{
"title": "Week of March 05 2017",
"startTime": "2017-03-05T05:00:00.000Z",
"endTime": "2017-03-12T04:59:59.000Z"
},
{
"title": "Week of March 12 2017",
"startTime": "2017-03-12T05:00:00.000Z",
"endTime": "2017-03-19T03:59:59.000Z"
},
{
"title": "Week of March 19 2017",
"startTime": "2017-03-19T04:00:00.000Z",
"endTime": "2017-03-26T03:59:59.000Z"
},
{
"title": "Week of March 26 2017",
"startTime": "2017-03-26T04:00:00.000Z",
"endTime": "2017-04-02T03:59:59.000Z"
}
];
////==============================
console.clear();
//Convert to real data objects...
for (const range of dateRanges) {
range.startTime = moment(range.startTime).utc().toDate();
range.endTime = moment(range.endTime).utc().toDate();
}
//OLD
const librarySort = _.sortBy(dateRanges, (range: IDateRange) => {
if (moment(range.endTime).diff(range.startTime, "days") > 7) {
return range.endTime;
} else {
return range.startTime;
}
});
//NEW - changes made here
const nativeSort = dateRanges.sort((r1: IDateRange, r2: IDateRange) => {
let firstPartToCompare;
let secondPartToCompare;
if(r1.title.indexOf('eek') > -1) {
firstPartToCompare = r1.startTime;
} else {
firstPartToCompare = r1.endTime;
}
if(r2.title.indexOf('eek') > -1) {
secondPartToCompare = r2.startTime;
} else {
secondPartToCompare = r2.endTime;
}
if (firstPartToCompare > secondPartToCompare) {
return 1;
} else if (firstPartToCompare < secondPartToCompare) {
return -1;
}
return 0;
});
console.info("CORRECT order - old way")
console.table(librarySort);
console.info("ATTEMPT to duplicate - new way")
console.table(nativeSort);